Home | History | Annotate | Download | only in libclang
      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 
     45 CXString createEmpty() {
     46   CXString Str;
     47   Str.data = "";
     48   Str.private_flags = CXS_Unmanaged;
     49   return Str;
     50 }
     51 
     52 CXString createNull() {
     53   CXString Str;
     54   Str.data = 0;
     55   Str.private_flags = CXS_Unmanaged;
     56   return Str;
     57 }
     58 
     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 
     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 
     82 CXString createRef(StringRef String) {
     83   // If the string is not nul-terminated, we have to make a copy.
     84   // This is doing a one past end read, and should be removed!
     85   if (!String.empty() && String.data()[String.size()] != 0)
     86     return createDup(String);
     87 
     88   CXString Result;
     89   Result.data = String.data();
     90   Result.private_flags = (unsigned) CXS_Unmanaged;
     91   return Result;
     92 }
     93 
     94 CXString createDup(StringRef String) {
     95   CXString Result;
     96   char *Spelling = static_cast<char *>(malloc(String.size() + 1));
     97   memmove(Spelling, String.data(), String.size());
     98   Spelling[String.size()] = 0;
     99   Result.data = Spelling;
    100   Result.private_flags = (unsigned) CXS_Malloc;
    101   return Result;
    102 }
    103 
    104 CXString createCXString(CXStringBuf *buf) {
    105   CXString Str;
    106   Str.data = buf;
    107   Str.private_flags = (unsigned) CXS_StringBuf;
    108   return Str;
    109 }
    110 
    111 
    112 //===----------------------------------------------------------------------===//
    113 // String pools.
    114 //===----------------------------------------------------------------------===//
    115 
    116 CXStringPool::~CXStringPool() {
    117   for (std::vector<CXStringBuf *>::iterator I = Pool.begin(), E = Pool.end();
    118        I != E; ++I) {
    119     delete *I;
    120   }
    121 }
    122 
    123 CXStringBuf *CXStringPool::getCXStringBuf(CXTranslationUnit TU) {
    124   if (Pool.empty())
    125     return new CXStringBuf(TU);
    126 
    127   CXStringBuf *Buf = Pool.back();
    128   Buf->Data.clear();
    129   Pool.pop_back();
    130   return Buf;
    131 }
    132 
    133 CXStringBuf *getCXStringBuf(CXTranslationUnit TU) {
    134   return TU->StringPool->getCXStringBuf(TU);
    135 }
    136 
    137 void CXStringBuf::dispose() {
    138   TU->StringPool->Pool.push_back(this);
    139 }
    140 
    141 bool isManagedByPool(CXString str) {
    142   return ((CXStringFlag) str.private_flags) == CXS_StringBuf;
    143 }
    144 
    145 } // end namespace cxstring
    146 } // end namespace clang
    147 
    148 //===----------------------------------------------------------------------===//
    149 // libClang public APIs.
    150 //===----------------------------------------------------------------------===//
    151 
    152 extern "C" {
    153 const char *clang_getCString(CXString string) {
    154   if (string.private_flags == (unsigned) CXS_StringBuf) {
    155     return static_cast<const cxstring::CXStringBuf *>(string.data)->Data.data();
    156   }
    157   return static_cast<const char *>(string.data);
    158 }
    159 
    160 void clang_disposeString(CXString string) {
    161   switch ((CXStringFlag) string.private_flags) {
    162     case CXS_Unmanaged:
    163       break;
    164     case CXS_Malloc:
    165       if (string.data)
    166         free(const_cast<void *>(string.data));
    167       break;
    168     case CXS_StringBuf:
    169       static_cast<cxstring::CXStringBuf *>(
    170           const_cast<void *>(string.data))->dispose();
    171       break;
    172   }
    173 }
    174 } // end: extern "C"
    175 
    176