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 SambucCXString 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 SambucCXString 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 SambucCXString 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 SambucCXString 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 SambucCXString 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 SambucCXString 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 SambucCXString 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 SambucCXStringPool::~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 SambucCXStringBuf *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 SambucCXStringBuf *getCXStringBuf(CXTranslationUnit TU) { 138f4a2713aSLionel Sambuc return TU->StringPool->getCXStringBuf(TU); 139f4a2713aSLionel Sambuc } 140f4a2713aSLionel Sambuc dispose()141f4a2713aSLionel Sambucvoid CXStringBuf::dispose() { 142f4a2713aSLionel Sambuc TU->StringPool->Pool.push_back(this); 143f4a2713aSLionel Sambuc } 144f4a2713aSLionel Sambuc isManagedByPool(CXString str)145f4a2713aSLionel Sambucbool 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 Sambucconst 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 Sambucvoid 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