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