CXString.cpp revision e358fd50a9b56e36f3f0f1a8f85bbb6d869cd117
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
23using namespace clang;
24using namespace clang::cxstring;
25
26enum CXStringFlag { CXS_Unmanaged, CXS_Malloc, CXS_StringBuf };
27
28//===----------------------------------------------------------------------===//
29// Basic generation of CXStrings.
30//===----------------------------------------------------------------------===//
31
32CXString 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 = String;
39    Str.private_flags = (unsigned) CXS_Unmanaged;
40  }
41  return Str;
42}
43
44CXString cxstring::createCXString(StringRef String, bool DupString) {
45  CXString Result;
46  if (DupString || (!String.empty() && String.data()[String.size()] != 0)) {
47    char *Spelling = static_cast<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 = String.data();
54    Result.private_flags = (unsigned) CXS_Unmanaged;
55  }
56  return Result;
57}
58
59CXString 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
72typedef std::vector<CXStringBuf *> CXStringPool;
73
74void *cxstring::createCXStringPool() {
75  return new CXStringPool();
76}
77
78void 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
89CXStringBuf *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
99void cxstring::disposeCXStringBuf(CXStringBuf *buf) {
100  if (buf)
101    static_cast<CXStringPool*>(buf->TU->StringPool)->push_back(buf);
102}
103
104bool cxstring::isManagedByPool(CXString str) {
105  return ((CXStringFlag) str.private_flags) == CXS_StringBuf;
106}
107
108//===----------------------------------------------------------------------===//
109// libClang public APIs.
110//===----------------------------------------------------------------------===//
111
112extern "C" {
113const char *clang_getCString(CXString string) {
114  if (string.private_flags == (unsigned) CXS_StringBuf) {
115    return static_cast<const CXStringBuf *>(string.data)->Data.data();
116  }
117  return static_cast<const char *>(string.data);
118}
119
120void clang_disposeString(CXString string) {
121  switch ((CXStringFlag) string.private_flags) {
122    case CXS_Unmanaged:
123      break;
124    case CXS_Malloc:
125      if (string.data)
126        free(const_cast<void *>(string.data));
127      break;
128    case CXS_StringBuf:
129      disposeCXStringBuf(static_cast<CXStringBuf *>(
130                             const_cast<void *>(string.data)));
131      break;
132  }
133}
134} // end: extern "C"
135
136