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