blob: f13a5a0415d7797fcee9e121bb574276215e67fc [file] [log] [blame]
Ted Kremenekea834df2010-11-16 02:03:55 +00001//===- 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"
Ted Kremenek0a90d322010-11-17 23:24:11 +000017#include "CXTranslationUnit.h"
Ted Kremenekea834df2010-11-16 02:03:55 +000018#include "clang-c/Index.h"
Chandler Carruthf59edb92012-12-04 09:25:21 +000019#include "clang/Frontend/ASTUnit.h"
Ted Kremeneka60ed472010-11-16 08:15:36 +000020#include "llvm/ADT/SmallString.h"
Ted Kremenekea834df2010-11-16 02:03:55 +000021#include "llvm/Support/ErrorHandling.h"
22
23using namespace clang;
24using namespace clang::cxstring;
25
Dmitri Gribenko17c1a242013-02-01 16:36:31 +000026/// Describes the kind of underlying data in CXString.
27enum CXStringFlag {
28 /// CXString contains a 'const char *' that it doesn't own.
29 CXS_Unmanaged,
30
31 /// CXString contains a 'const char *' that it allocated with malloc().
32 CXS_Malloc,
33
34 /// CXString contains a CXStringBuf that needs to be returned to the
35 /// CXStringPool.
36 CXS_StringBuf
37};
Ted Kremeneka60ed472010-11-16 08:15:36 +000038
39//===----------------------------------------------------------------------===//
40// Basic generation of CXStrings.
41//===----------------------------------------------------------------------===//
Ted Kremenekea834df2010-11-16 02:03:55 +000042
Dmitri Gribenkodc66adb2013-02-01 14:21:22 +000043CXString cxstring::createEmpty() {
44 CXString Str;
45 Str.data = "";
46 Str.private_flags = CXS_Unmanaged;
47 return Str;
48}
49
Dmitri Gribenkodad4c1a2013-02-01 14:13:32 +000050CXString cxstring::createNull() {
51 CXString Str;
52 Str.data = 0;
53 Str.private_flags = CXS_Unmanaged;
54 return Str;
55}
56
Dmitri Gribenko0c4394c2013-02-02 00:02:12 +000057CXString cxstring::createRef(const char *String) {
58 if (String && String[0] == '\0')
59 return cxstring::createEmpty();
60
Ted Kremenekea834df2010-11-16 02:03:55 +000061 CXString Str;
Dmitri Gribenko0c4394c2013-02-02 00:02:12 +000062 Str.data = String;
63 Str.private_flags = CXS_Unmanaged;
64 return Str;
65}
66
67CXString cxstring::createDup(const char *String) {
68 if (!String)
69 return cxstring::createNull();
70
71 if (String[0] == '\0')
72 return cxstring::createEmpty();
73
74 CXString Str;
75 Str.data = strdup(String);
76 Str.private_flags = CXS_Malloc;
Ted Kremenekea834df2010-11-16 02:03:55 +000077 return Str;
78}
79
Chris Lattner5f9e2722011-07-23 10:55:15 +000080CXString cxstring::createCXString(StringRef String, bool DupString) {
Ted Kremenekea834df2010-11-16 02:03:55 +000081 CXString Result;
82 if (DupString || (!String.empty() && String.data()[String.size()] != 0)) {
Dmitri Gribenkoe358fd52013-01-11 23:13:36 +000083 char *Spelling = static_cast<char *>(malloc(String.size() + 1));
Ted Kremenekea834df2010-11-16 02:03:55 +000084 memmove(Spelling, String.data(), String.size());
85 Spelling[String.size()] = 0;
Ted Kremeneka60ed472010-11-16 08:15:36 +000086 Result.data = Spelling;
Ted Kremenekea834df2010-11-16 02:03:55 +000087 Result.private_flags = (unsigned) CXS_Malloc;
88 } else {
Dmitri Gribenko689d7472013-01-11 23:08:18 +000089 Result.data = String.data();
Ted Kremenekea834df2010-11-16 02:03:55 +000090 Result.private_flags = (unsigned) CXS_Unmanaged;
91 }
92 return Result;
93}
94
Ted Kremeneka60ed472010-11-16 08:15:36 +000095CXString cxstring::createCXString(CXStringBuf *buf) {
96 CXString Str;
97 Str.data = buf;
98 Str.private_flags = (unsigned) CXS_StringBuf;
99 return Str;
100}
101
102
103//===----------------------------------------------------------------------===//
104// String pools.
105//===----------------------------------------------------------------------===//
106
Dmitri Gribenko9c48d162013-01-26 22:44:19 +0000107cxstring::CXStringPool::~CXStringPool() {
108 for (std::vector<CXStringBuf *>::iterator I = Pool.begin(), E = Pool.end();
109 I != E; ++I) {
110 delete *I;
Ted Kremeneka60ed472010-11-16 08:15:36 +0000111 }
112}
113
Dmitri Gribenko9c48d162013-01-26 22:44:19 +0000114CXStringBuf *cxstring::CXStringPool::getCXStringBuf(CXTranslationUnit TU) {
115 if (Pool.empty())
Ted Kremeneka60ed472010-11-16 08:15:36 +0000116 return new CXStringBuf(TU);
Dmitri Gribenko9c48d162013-01-26 22:44:19 +0000117
118 CXStringBuf *Buf = Pool.back();
119 Buf->Data.clear();
120 Pool.pop_back();
121 return Buf;
Ted Kremeneka60ed472010-11-16 08:15:36 +0000122}
123
Dmitri Gribenko9c48d162013-01-26 22:44:19 +0000124CXStringBuf *cxstring::getCXStringBuf(CXTranslationUnit TU) {
125 return TU->StringPool->getCXStringBuf(TU);
126}
127
128void cxstring::CXStringBuf::dispose() {
129 TU->StringPool->Pool.push_back(this);
Ted Kremeneka60ed472010-11-16 08:15:36 +0000130}
131
Ted Kremenekbaf82b02011-08-17 22:19:53 +0000132bool cxstring::isManagedByPool(CXString str) {
133 return ((CXStringFlag) str.private_flags) == CXS_StringBuf;
134}
135
Ted Kremenekea834df2010-11-16 02:03:55 +0000136//===----------------------------------------------------------------------===//
137// libClang public APIs.
138//===----------------------------------------------------------------------===//
139
140extern "C" {
141const char *clang_getCString(CXString string) {
Ted Kremeneka60ed472010-11-16 08:15:36 +0000142 if (string.private_flags == (unsigned) CXS_StringBuf) {
Dmitri Gribenkoe358fd52013-01-11 23:13:36 +0000143 return static_cast<const CXStringBuf *>(string.data)->Data.data();
Ted Kremeneka60ed472010-11-16 08:15:36 +0000144 }
Dmitri Gribenkoe358fd52013-01-11 23:13:36 +0000145 return static_cast<const char *>(string.data);
Ted Kremenekea834df2010-11-16 02:03:55 +0000146}
147
148void clang_disposeString(CXString string) {
Ted Kremeneka60ed472010-11-16 08:15:36 +0000149 switch ((CXStringFlag) string.private_flags) {
150 case CXS_Unmanaged:
151 break;
152 case CXS_Malloc:
153 if (string.data)
Dmitri Gribenko689d7472013-01-11 23:08:18 +0000154 free(const_cast<void *>(string.data));
Ted Kremeneka60ed472010-11-16 08:15:36 +0000155 break;
156 case CXS_StringBuf:
Dmitri Gribenko9c48d162013-01-26 22:44:19 +0000157 static_cast<CXStringBuf *>(
158 const_cast<void *>(string.data))->dispose();
Ted Kremeneka60ed472010-11-16 08:15:36 +0000159 break;
160 }
Ted Kremenekea834df2010-11-16 02:03:55 +0000161}
162} // end: extern "C"
163