Clang Project

clang_source_code/tools/libclang/CXString.cpp
1//===- CXString.cpp - Routines for manipulating CXStrings -----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines routines for manipulating CXStrings. It should be the
10// only file that has internal knowledge of the encoding of the data in
11// CXStrings.
12//
13//===----------------------------------------------------------------------===//
14
15#include "CXString.h"
16#include "CXTranslationUnit.h"
17#include "clang-c/Index.h"
18#include "clang/Frontend/ASTUnit.h"
19#include "llvm/Support/ErrorHandling.h"
20
21using namespace clang;
22
23/// Describes the kind of underlying data in CXString.
24enum CXStringFlag {
25  /// CXString contains a 'const char *' that it doesn't own.
26  CXS_Unmanaged,
27
28  /// CXString contains a 'const char *' that it allocated with malloc().
29  CXS_Malloc,
30
31  /// CXString contains a CXStringBuf that needs to be returned to the
32  /// CXStringPool.
33  CXS_StringBuf
34};
35
36namespace clang {
37namespace cxstring {
38
39//===----------------------------------------------------------------------===//
40// Basic generation of CXStrings.
41//===----------------------------------------------------------------------===//
42
43CXString createEmpty() {
44  CXString Str;
45  Str.data = "";
46  Str.private_flags = CXS_Unmanaged;
47  return Str;
48}
49
50CXString createNull() {
51  CXString Str;
52  Str.data = nullptr;
53  Str.private_flags = CXS_Unmanaged;
54  return Str;
55}
56
57CXString createRef(const char *String) {
58  if (String && String[0] == '\0')
59    return createEmpty();
60
61  CXString Str;
62  Str.data = String;
63  Str.private_flags = CXS_Unmanaged;
64  return Str;
65}
66
67CXString createDup(const char *String) {
68  if (!String)
69    return createNull();
70
71  if (String[0] == '\0')
72    return createEmpty();
73
74  CXString Str;
75  Str.data = strdup(String);
76  Str.private_flags = CXS_Malloc;
77  return Str;
78}
79
80CXString createRef(StringRef String) {
81  // If the string is not nul-terminated, we have to make a copy.
82
83  // FIXME: This is doing a one past end read, and should be removed! For memory
84  // we don't manage, the API string can become unterminated at any time outside
85  // our control.
86
87  if (!String.empty() && String.data()[String.size()] != 0)
88    return createDup(String);
89
90  CXString Result;
91  Result.data = String.data();
92  Result.private_flags = (unsignedCXS_Unmanaged;
93  return Result;
94}
95
96CXString createDup(StringRef String) {
97  CXString Result;
98  char *Spelling = static_cast<char *>(llvm::safe_malloc(String.size() + 1));
99  memmove(Spelling, String.data(), String.size());
100  Spelling[String.size()] = 0;
101  Result.data = Spelling;
102  Result.private_flags = (unsignedCXS_Malloc;
103  return Result;
104}
105
106CXString createCXString(CXStringBuf *buf) {
107  CXString Str;
108  Str.data = buf;
109  Str.private_flags = (unsignedCXS_StringBuf;
110  return Str;
111}
112
113CXStringSet *createSet(const std::vector<std::string> &Strings) {
114  CXStringSet *Set = new CXStringSet;
115  Set->Count = Strings.size();
116  Set->Strings = new CXString[Set->Count];
117  for (unsigned SI = 0, SE = Set->Count; SI < SE; ++SI)
118    Set->Strings[SI] = createDup(Strings[SI]);
119  return Set;
120}
121
122
123//===----------------------------------------------------------------------===//
124// String pools.
125//===----------------------------------------------------------------------===//
126
127CXStringPool::~CXStringPool() {
128  for (std::vector<CXStringBuf *>::iterator I = Pool.begin(), E = Pool.end();
129       I != E; ++I) {
130    delete *I;
131  }
132}
133
134CXStringBuf *CXStringPool::getCXStringBuf(CXTranslationUnit TU) {
135  if (Pool.empty())
136    return new CXStringBuf(TU);
137
138  CXStringBuf *Buf = Pool.back();
139  Buf->Data.clear();
140  Pool.pop_back();
141  return Buf;
142}
143
144CXStringBuf *getCXStringBuf(CXTranslationUnit TU) {
145  return TU->StringPool->getCXStringBuf(TU);
146}
147
148void CXStringBuf::dispose() {
149  TU->StringPool->Pool.push_back(this);
150}
151
152bool isManagedByPool(CXString str) {
153  return ((CXStringFlagstr.private_flags) == CXS_StringBuf;
154}
155
156// end namespace cxstring
157// end namespace clang
158
159//===----------------------------------------------------------------------===//
160// libClang public APIs.
161//===----------------------------------------------------------------------===//
162
163const char *clang_getCString(CXString string) {
164  if (string.private_flags == (unsignedCXS_StringBuf) {
165    return static_cast<const cxstring::CXStringBuf *>(string.data)->Data.data();
166  }
167  return static_cast<const char *>(string.data);
168}
169
170void clang_disposeString(CXString string) {
171  switch ((CXStringFlagstring.private_flags) {
172    case CXS_Unmanaged:
173      break;
174    case CXS_Malloc:
175      if (string.data)
176        free(const_cast<void *>(string.data));
177      break;
178    case CXS_StringBuf:
179      static_cast<cxstring::CXStringBuf *>(
180          const_cast<void *>(string.data))->dispose();
181      break;
182  }
183}
184
185void clang_disposeStringSet(CXStringSet *set) {
186  for (unsigned SI = 0SE = set->CountSI < SE; ++SI)
187    clang_disposeString(set->Strings[SI]);
188  delete[] set->Strings;
189  delete set;
190}
191
192
clang::cxstring::CXStringPool::getCXStringBuf
clang::cxstring::CXStringBuf::dispose