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/Frontend/ASTUnit.h"
19 #include "clang-c/Index.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/Support/ErrorHandling.h"
22 
23 using namespace clang;
24 using namespace clang::cxstring;
25 
26 enum CXStringFlag { CXS_Unmanaged, CXS_Malloc, CXS_StringBuf };
27 
28 //===----------------------------------------------------------------------===//
29 // Basic generation of CXStrings.
30 //===----------------------------------------------------------------------===//
31 
32 CXString cxstring::createCXString(const char *String, bool DupString){
33   CXString Str;
34   if (DupString) {
35     Str.data = strdup(String);
36     Str.private_flags = (unsigned) CXS_Malloc;
37   } else {
38     Str.data = (void*)String;
39     Str.private_flags = (unsigned) CXS_Unmanaged;
40   }
41   return Str;
42 }
43 
44 CXString cxstring::createCXString(llvm::StringRef String, bool DupString) {
45   CXString Result;
46   if (DupString || (!String.empty() && String.data()[String.size()] != 0)) {
47     char *Spelling = (char *)malloc(String.size() + 1);
48     memmove(Spelling, String.data(), String.size());
49     Spelling[String.size()] = 0;
50     Result.data = Spelling;
51     Result.private_flags = (unsigned) CXS_Malloc;
52   } else {
53     Result.data = (void*) String.data();
54     Result.private_flags = (unsigned) CXS_Unmanaged;
55   }
56   return Result;
57 }
58 
59 CXString cxstring::createCXString(CXStringBuf *buf) {
60   CXString Str;
61   Str.data = buf;
62   Str.private_flags = (unsigned) CXS_StringBuf;
63   return Str;
64 }
65 
66 
67 //===----------------------------------------------------------------------===//
68 // String pools.
69 //===----------------------------------------------------------------------===//
70 
71 
72 typedef std::vector<CXStringBuf *> CXStringPool;
73 
74 void *cxstring::createCXStringPool() {
75   return new CXStringPool();
76 }
77 
78 void cxstring::disposeCXStringPool(void *p) {
79   CXStringPool *pool = static_cast<CXStringPool*>(p);
80   if (pool) {
81     for (CXStringPool::iterator I = pool->begin(), E = pool->end();
82          I != E; ++I) {
83       delete *I;
84     }
85     delete pool;
86   }
87 }
88 
89 CXStringBuf *cxstring::getCXStringBuf(CXTranslationUnit TU) {
90   CXStringPool *pool = static_cast<CXStringPool*>(TU->StringPool);
91   if (pool->empty())
92     return new CXStringBuf(TU);
93   CXStringBuf *buf = pool->back();
94   buf->Data.clear();
95   pool->pop_back();
96   return buf;
97 }
98 
99 void cxstring::disposeCXStringBuf(CXStringBuf *buf) {
100   if (buf)
101     static_cast<CXStringPool*>(buf->TU->StringPool)->push_back(buf);
102 }
103 
104 //===----------------------------------------------------------------------===//
105 // libClang public APIs.
106 //===----------------------------------------------------------------------===//
107 
108 extern "C" {
109 const char *clang_getCString(CXString string) {
110   if (string.private_flags == (unsigned) CXS_StringBuf) {
111     return ((CXStringBuf*)string.data)->Data.data();
112   }
113   return (const char*) string.data;
114 }
115 
116 void clang_disposeString(CXString string) {
117   switch ((CXStringFlag) string.private_flags) {
118     case CXS_Unmanaged:
119       break;
120     case CXS_Malloc:
121       if (string.data)
122         free((void*)string.data);
123       break;
124     case CXS_StringBuf:
125       disposeCXStringBuf((CXStringBuf *) string.data);
126       break;
127   }
128 }
129 } // end: extern "C"
130 
131