blob: 2148181ef84cc20321e38b94cb6618f8776e9da8 [file] [log] [blame]
Ted Kremenek64dddfb2010-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 Kremenek7df92ae2010-11-17 23:24:11 +000017#include "CXTranslationUnit.h"
Ted Kremenek64dddfb2010-11-16 02:03:55 +000018#include "clang-c/Index.h"
Chandler Carruthcc0694c2012-12-04 09:25:21 +000019#include "clang/Frontend/ASTUnit.h"
Ted Kremenek64dddfb2010-11-16 02:03:55 +000020#include "llvm/Support/ErrorHandling.h"
21
22using namespace clang;
Ted Kremenek64dddfb2010-11-16 02:03:55 +000023
Dmitri Gribenko74f3e1e2013-02-01 16:36:31 +000024/// Describes the kind of underlying data in CXString.
25enum CXStringFlag {
26 /// CXString contains a 'const char *' that it doesn't own.
27 CXS_Unmanaged,
28
29 /// CXString contains a 'const char *' that it allocated with malloc().
30 CXS_Malloc,
31
32 /// CXString contains a CXStringBuf that needs to be returned to the
33 /// CXStringPool.
34 CXS_StringBuf
35};
Ted Kremenek91554282010-11-16 08:15:36 +000036
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +000037namespace clang {
38namespace cxstring {
39
Ted Kremenek91554282010-11-16 08:15:36 +000040//===----------------------------------------------------------------------===//
41// Basic generation of CXStrings.
42//===----------------------------------------------------------------------===//
Ted Kremenek64dddfb2010-11-16 02:03:55 +000043
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +000044CXString createEmpty() {
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +000045 CXString Str;
46 Str.data = "";
47 Str.private_flags = CXS_Unmanaged;
48 return Str;
49}
50
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +000051CXString createNull() {
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +000052 CXString Str;
Craig Topper69186e72014-06-08 08:38:04 +000053 Str.data = nullptr;
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +000054 Str.private_flags = CXS_Unmanaged;
55 return Str;
56}
57
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +000058CXString createRef(const char *String) {
Dmitri Gribenko3c66b0b2013-02-02 00:02:12 +000059 if (String && String[0] == '\0')
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +000060 return createEmpty();
Dmitri Gribenko3c66b0b2013-02-02 00:02:12 +000061
Ted Kremenek64dddfb2010-11-16 02:03:55 +000062 CXString Str;
Dmitri Gribenko3c66b0b2013-02-02 00:02:12 +000063 Str.data = String;
64 Str.private_flags = CXS_Unmanaged;
65 return Str;
66}
67
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +000068CXString createDup(const char *String) {
Dmitri Gribenko3c66b0b2013-02-02 00:02:12 +000069 if (!String)
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +000070 return createNull();
Dmitri Gribenko3c66b0b2013-02-02 00:02:12 +000071
72 if (String[0] == '\0')
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +000073 return createEmpty();
Dmitri Gribenko3c66b0b2013-02-02 00:02:12 +000074
75 CXString Str;
76 Str.data = strdup(String);
77 Str.private_flags = CXS_Malloc;
Ted Kremenek64dddfb2010-11-16 02:03:55 +000078 return Str;
79}
80
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +000081CXString createRef(StringRef String) {
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +000082 // If the string is not nul-terminated, we have to make a copy.
Alp Toker541d5072014-06-07 23:30:53 +000083
84 // FIXME: This is doing a one past end read, and should be removed! For memory
85 // we don't manage, the API string can become unterminated at any time outside
86 // our control.
87
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +000088 if (!String.empty() && String.data()[String.size()] != 0)
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +000089 return createDup(String);
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +000090
Ted Kremenek64dddfb2010-11-16 02:03:55 +000091 CXString Result;
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +000092 Result.data = String.data();
93 Result.private_flags = (unsigned) CXS_Unmanaged;
94 return Result;
95}
96
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +000097CXString createDup(StringRef String) {
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +000098 CXString Result;
99 char *Spelling = static_cast<char *>(malloc(String.size() + 1));
100 memmove(Spelling, String.data(), String.size());
101 Spelling[String.size()] = 0;
102 Result.data = Spelling;
103 Result.private_flags = (unsigned) CXS_Malloc;
Ted Kremenek64dddfb2010-11-16 02:03:55 +0000104 return Result;
105}
106
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +0000107CXString createCXString(CXStringBuf *buf) {
Ted Kremenek91554282010-11-16 08:15:36 +0000108 CXString Str;
109 Str.data = buf;
110 Str.private_flags = (unsigned) CXS_StringBuf;
111 return Str;
112}
113
Saleem Abdulrasool5d92eae2015-11-12 03:57:16 +0000114CXStringSet *createSet(const std::vector<std::string> &Strings) {
115 CXStringSet *Set = new CXStringSet;
116 Set->Count = Strings.size();
117 Set->Strings = new CXString[Set->Count];
118 for (unsigned SI = 0, SE = Set->Count; SI < SE; ++SI)
119 Set->Strings[SI] = createDup(Strings[SI]);
120 return Set;
121}
122
Ted Kremenek91554282010-11-16 08:15:36 +0000123
124//===----------------------------------------------------------------------===//
125// String pools.
126//===----------------------------------------------------------------------===//
127
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +0000128CXStringPool::~CXStringPool() {
Dmitri Gribenkob95b3f12013-01-26 22:44:19 +0000129 for (std::vector<CXStringBuf *>::iterator I = Pool.begin(), E = Pool.end();
130 I != E; ++I) {
131 delete *I;
Ted Kremenek91554282010-11-16 08:15:36 +0000132 }
133}
134
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +0000135CXStringBuf *CXStringPool::getCXStringBuf(CXTranslationUnit TU) {
Dmitri Gribenkob95b3f12013-01-26 22:44:19 +0000136 if (Pool.empty())
Ted Kremenek91554282010-11-16 08:15:36 +0000137 return new CXStringBuf(TU);
Dmitri Gribenkob95b3f12013-01-26 22:44:19 +0000138
139 CXStringBuf *Buf = Pool.back();
140 Buf->Data.clear();
141 Pool.pop_back();
142 return Buf;
Ted Kremenek91554282010-11-16 08:15:36 +0000143}
144
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +0000145CXStringBuf *getCXStringBuf(CXTranslationUnit TU) {
Dmitri Gribenkob95b3f12013-01-26 22:44:19 +0000146 return TU->StringPool->getCXStringBuf(TU);
147}
148
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +0000149void CXStringBuf::dispose() {
Dmitri Gribenkob95b3f12013-01-26 22:44:19 +0000150 TU->StringPool->Pool.push_back(this);
Ted Kremenek91554282010-11-16 08:15:36 +0000151}
152
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +0000153bool isManagedByPool(CXString str) {
Ted Kremenek5b8ad402011-08-17 22:19:53 +0000154 return ((CXStringFlag) str.private_flags) == CXS_StringBuf;
155}
156
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +0000157} // end namespace cxstring
158} // end namespace clang
159
Ted Kremenek64dddfb2010-11-16 02:03:55 +0000160//===----------------------------------------------------------------------===//
161// libClang public APIs.
162//===----------------------------------------------------------------------===//
163
164extern "C" {
165const char *clang_getCString(CXString string) {
Ted Kremenek91554282010-11-16 08:15:36 +0000166 if (string.private_flags == (unsigned) CXS_StringBuf) {
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +0000167 return static_cast<const cxstring::CXStringBuf *>(string.data)->Data.data();
Ted Kremenek91554282010-11-16 08:15:36 +0000168 }
Dmitri Gribenko037f9d12013-01-11 23:13:36 +0000169 return static_cast<const char *>(string.data);
Ted Kremenek64dddfb2010-11-16 02:03:55 +0000170}
171
172void clang_disposeString(CXString string) {
Ted Kremenek91554282010-11-16 08:15:36 +0000173 switch ((CXStringFlag) string.private_flags) {
174 case CXS_Unmanaged:
175 break;
176 case CXS_Malloc:
177 if (string.data)
Dmitri Gribenkoec3a16f2013-01-11 23:08:18 +0000178 free(const_cast<void *>(string.data));
Ted Kremenek91554282010-11-16 08:15:36 +0000179 break;
180 case CXS_StringBuf:
Dmitri Gribenko18aa3bb2013-02-03 13:54:26 +0000181 static_cast<cxstring::CXStringBuf *>(
Dmitri Gribenkob95b3f12013-01-26 22:44:19 +0000182 const_cast<void *>(string.data))->dispose();
Ted Kremenek91554282010-11-16 08:15:36 +0000183 break;
184 }
Ted Kremenek64dddfb2010-11-16 02:03:55 +0000185}
Saleem Abdulrasool5d92eae2015-11-12 03:57:16 +0000186
187void clang_disposeStringSet(CXStringSet *set) {
Reid Kleckner356be392015-11-18 01:06:39 +0000188 for (unsigned SI = 0, SE = set->Count; SI < SE; ++SI)
189 clang_disposeString(set->Strings[SI]);
Saleem Abdulrasool5d92eae2015-11-12 03:57:16 +0000190 delete[] set->Strings;
191 delete set;
192}
193
Ted Kremenek64dddfb2010-11-16 02:03:55 +0000194} // end: extern "C"
195