189 lines · cpp
1//===- CXString.cpp - Routines for manipulating CXStrings -----------------===//2//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines routines for manipulating CXStrings. It should be the10// only file that has internal knowledge of the encoding of the data in11// CXStrings.12//13//===----------------------------------------------------------------------===//14 15#include "CXString.h"16#include "CXTranslationUnit.h"17#include "clang-c/Index.h"18#include "clang/Frontend/ASTUnit.h"19#include "llvm/Support/ErrorHandling.h"20 21using namespace clang;22 23/// Describes the kind of underlying data in CXString.24enum CXStringFlag {25 /// CXString contains a 'const char *' that it doesn't own.26 CXS_Unmanaged,27 28 /// CXString contains a 'const char *' that it allocated with malloc().29 CXS_Malloc,30 31 /// CXString contains a CXStringBuf that needs to be returned to the32 /// CXStringPool.33 CXS_StringBuf34};35 36namespace clang {37namespace cxstring {38 39//===----------------------------------------------------------------------===//40// Basic generation of CXStrings.41//===----------------------------------------------------------------------===//42 43CXString createEmpty() {44 CXString Str;45 Str.data = "";46 Str.private_flags = CXS_Unmanaged;47 return Str;48}49 50CXString createNull() {51 CXString Str;52 Str.data = nullptr;53 Str.private_flags = CXS_Unmanaged;54 return Str;55}56 57CXString createRef(const char *String) {58 if (String && String[0] == '\0')59 return createEmpty();60 61 CXString Str;62 Str.data = String;63 Str.private_flags = CXS_Unmanaged;64 return Str;65}66 67CXString createDup(const char *String) {68 if (!String)69 return createNull();70 71 if (String[0] == '\0')72 return createEmpty();73 74 CXString Str;75 Str.data = strdup(String);76 Str.private_flags = CXS_Malloc;77 return Str;78}79 80CXString createRef(StringRef String) {81 if (!String.data())82 return createNull();83 84 // If the string is empty, it might point to a position in another string85 // while having zero length. Make sure we don't create a reference to the86 // larger string.87 if (String.empty())88 return createEmpty();89 90 return createDup(String);91}92 93CXString createDup(StringRef String) {94 CXString Result;95 char *Spelling = static_cast<char *>(llvm::safe_malloc(String.size() + 1));96 memmove(Spelling, String.data(), String.size());97 Spelling[String.size()] = 0;98 Result.data = Spelling;99 Result.private_flags = (unsigned) CXS_Malloc;100 return Result;101}102 103CXString createCXString(CXStringBuf *buf) {104 CXString Str;105 Str.data = buf;106 Str.private_flags = (unsigned) CXS_StringBuf;107 return Str;108}109 110CXStringSet *createSet(const std::vector<std::string> &Strings) {111 CXStringSet *Set = new CXStringSet;112 Set->Count = Strings.size();113 Set->Strings = new CXString[Set->Count];114 for (unsigned SI = 0, SE = Set->Count; SI < SE; ++SI)115 Set->Strings[SI] = createDup(Strings[SI]);116 return Set;117}118 119 120//===----------------------------------------------------------------------===//121// String pools.122//===----------------------------------------------------------------------===//123 124CXStringPool::~CXStringPool() {125 for (std::vector<CXStringBuf *>::iterator I = Pool.begin(), E = Pool.end();126 I != E; ++I) {127 delete *I;128 }129}130 131CXStringBuf *CXStringPool::getCXStringBuf(CXTranslationUnit TU) {132 if (Pool.empty())133 return new CXStringBuf(TU);134 135 CXStringBuf *Buf = Pool.back();136 Buf->Data.clear();137 Pool.pop_back();138 return Buf;139}140 141CXStringBuf *getCXStringBuf(CXTranslationUnit TU) {142 return TU->StringPool->getCXStringBuf(TU);143}144 145void CXStringBuf::dispose() {146 TU->StringPool->Pool.push_back(this);147}148 149bool isManagedByPool(CXString str) {150 return ((CXStringFlag) str.private_flags) == CXS_StringBuf;151}152 153} // end namespace cxstring154} // end namespace clang155 156//===----------------------------------------------------------------------===//157// libClang public APIs.158//===----------------------------------------------------------------------===//159 160const char *clang_getCString(CXString string) {161 if (string.private_flags == (unsigned) CXS_StringBuf) {162 return static_cast<const cxstring::CXStringBuf *>(string.data)->Data.data();163 }164 return static_cast<const char *>(string.data);165}166 167void clang_disposeString(CXString string) {168 switch ((CXStringFlag) string.private_flags) {169 case CXS_Unmanaged:170 break;171 case CXS_Malloc:172 if (string.data)173 free(const_cast<void *>(string.data));174 break;175 case CXS_StringBuf:176 static_cast<cxstring::CXStringBuf *>(177 const_cast<void *>(string.data))->dispose();178 break;179 }180}181 182void clang_disposeStringSet(CXStringSet *set) {183 for (unsigned SI = 0, SE = set->Count; SI < SE; ++SI)184 clang_disposeString(set->Strings[SI]);185 delete[] set->Strings;186 delete set;187}188 189