1 //===- CXString.cpp - Routines for manipulating CXStrings -----------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines routines for manipulating CXStrings. It should be the
10 // only file that has internal knowledge of the encoding of the data in
13 //===----------------------------------------------------------------------===//
16 #include "CXTranslationUnit.h"
17 #include "clang-c/Index.h"
18 #include "clang/Frontend/ASTUnit.h"
19 #include "llvm/Support/ErrorHandling.h"
21 using namespace clang
;
23 /// Describes the kind of underlying data in CXString.
25 /// CXString contains a 'const char *' that it doesn't own.
28 /// CXString contains a 'const char *' that it allocated with malloc().
31 /// CXString contains a CXStringBuf that needs to be returned to the
39 //===----------------------------------------------------------------------===//
40 // Basic generation of CXStrings.
41 //===----------------------------------------------------------------------===//
43 CXString
createEmpty() {
46 Str
.private_flags
= CXS_Unmanaged
;
50 CXString
createNull() {
53 Str
.private_flags
= CXS_Unmanaged
;
57 CXString
createRef(const char *String
) {
58 if (String
&& String
[0] == '\0')
63 Str
.private_flags
= CXS_Unmanaged
;
67 CXString
createDup(const char *String
) {
71 if (String
[0] == '\0')
75 Str
.data
= strdup(String
);
76 Str
.private_flags
= CXS_Malloc
;
80 CXString
createRef(StringRef String
) {
84 // If the string is empty, it might point to a position in another string
85 // while having zero length. Make sure we don't create a reference to the
90 // If the string is not nul-terminated, we have to make a copy.
92 // FIXME: This is doing a one past end read, and should be removed! For memory
93 // we don't manage, the API string can become unterminated at any time outside
96 if (String
.data()[String
.size()] != 0)
97 return createDup(String
);
100 Result
.data
= String
.data();
101 Result
.private_flags
= (unsigned) CXS_Unmanaged
;
105 CXString
createDup(StringRef String
) {
107 char *Spelling
= static_cast<char *>(llvm::safe_malloc(String
.size() + 1));
108 memmove(Spelling
, String
.data(), String
.size());
109 Spelling
[String
.size()] = 0;
110 Result
.data
= Spelling
;
111 Result
.private_flags
= (unsigned) CXS_Malloc
;
115 CXString
createCXString(CXStringBuf
*buf
) {
118 Str
.private_flags
= (unsigned) CXS_StringBuf
;
122 CXStringSet
*createSet(const std::vector
<std::string
> &Strings
) {
123 CXStringSet
*Set
= new CXStringSet
;
124 Set
->Count
= Strings
.size();
125 Set
->Strings
= new CXString
[Set
->Count
];
126 for (unsigned SI
= 0, SE
= Set
->Count
; SI
< SE
; ++SI
)
127 Set
->Strings
[SI
] = createDup(Strings
[SI
]);
132 //===----------------------------------------------------------------------===//
134 //===----------------------------------------------------------------------===//
136 CXStringPool::~CXStringPool() {
137 for (std::vector
<CXStringBuf
*>::iterator I
= Pool
.begin(), E
= Pool
.end();
143 CXStringBuf
*CXStringPool::getCXStringBuf(CXTranslationUnit TU
) {
145 return new CXStringBuf(TU
);
147 CXStringBuf
*Buf
= Pool
.back();
153 CXStringBuf
*getCXStringBuf(CXTranslationUnit TU
) {
154 return TU
->StringPool
->getCXStringBuf(TU
);
157 void CXStringBuf::dispose() {
158 TU
->StringPool
->Pool
.push_back(this);
161 bool isManagedByPool(CXString str
) {
162 return ((CXStringFlag
) str
.private_flags
) == CXS_StringBuf
;
165 } // end namespace cxstring
166 } // end namespace clang
168 //===----------------------------------------------------------------------===//
169 // libClang public APIs.
170 //===----------------------------------------------------------------------===//
172 const char *clang_getCString(CXString string
) {
173 if (string
.private_flags
== (unsigned) CXS_StringBuf
) {
174 return static_cast<const cxstring::CXStringBuf
*>(string
.data
)->Data
.data();
176 return static_cast<const char *>(string
.data
);
179 void clang_disposeString(CXString string
) {
180 switch ((CXStringFlag
) string
.private_flags
) {
185 free(const_cast<void *>(string
.data
));
188 static_cast<cxstring::CXStringBuf
*>(
189 const_cast<void *>(string
.data
))->dispose();
194 void clang_disposeStringSet(CXStringSet
*set
) {
195 for (unsigned SI
= 0, SE
= set
->Count
; SI
< SE
; ++SI
)
196 clang_disposeString(set
->Strings
[SI
]);
197 delete[] set
->Strings
;