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