teak-llvm/clang/tools/libclang/CXString.cpp
Chandler Carruth 2946cd7010 Update the file headers across all of the LLVM projects in the monorepo
to reflect the new license.

We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.

Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.

llvm-svn: 351636
2019-01-19 08:50:56 +00:00

192 lines
5.0 KiB
C++

//===- CXString.cpp - Routines for manipulating CXStrings -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines routines for manipulating CXStrings. It should be the
// only file that has internal knowledge of the encoding of the data in
// CXStrings.
//
//===----------------------------------------------------------------------===//
#include "CXString.h"
#include "CXTranslationUnit.h"
#include "clang-c/Index.h"
#include "clang/Frontend/ASTUnit.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
/// Describes the kind of underlying data in CXString.
enum CXStringFlag {
/// CXString contains a 'const char *' that it doesn't own.
CXS_Unmanaged,
/// CXString contains a 'const char *' that it allocated with malloc().
CXS_Malloc,
/// CXString contains a CXStringBuf that needs to be returned to the
/// CXStringPool.
CXS_StringBuf
};
namespace clang {
namespace cxstring {
//===----------------------------------------------------------------------===//
// Basic generation of CXStrings.
//===----------------------------------------------------------------------===//
CXString createEmpty() {
CXString Str;
Str.data = "";
Str.private_flags = CXS_Unmanaged;
return Str;
}
CXString createNull() {
CXString Str;
Str.data = nullptr;
Str.private_flags = CXS_Unmanaged;
return Str;
}
CXString createRef(const char *String) {
if (String && String[0] == '\0')
return createEmpty();
CXString Str;
Str.data = String;
Str.private_flags = CXS_Unmanaged;
return Str;
}
CXString createDup(const char *String) {
if (!String)
return createNull();
if (String[0] == '\0')
return createEmpty();
CXString Str;
Str.data = strdup(String);
Str.private_flags = CXS_Malloc;
return Str;
}
CXString createRef(StringRef String) {
// If the string is not nul-terminated, we have to make a copy.
// FIXME: This is doing a one past end read, and should be removed! For memory
// we don't manage, the API string can become unterminated at any time outside
// our control.
if (!String.empty() && String.data()[String.size()] != 0)
return createDup(String);
CXString Result;
Result.data = String.data();
Result.private_flags = (unsigned) CXS_Unmanaged;
return Result;
}
CXString createDup(StringRef String) {
CXString Result;
char *Spelling = static_cast<char *>(llvm::safe_malloc(String.size() + 1));
memmove(Spelling, String.data(), String.size());
Spelling[String.size()] = 0;
Result.data = Spelling;
Result.private_flags = (unsigned) CXS_Malloc;
return Result;
}
CXString createCXString(CXStringBuf *buf) {
CXString Str;
Str.data = buf;
Str.private_flags = (unsigned) CXS_StringBuf;
return Str;
}
CXStringSet *createSet(const std::vector<std::string> &Strings) {
CXStringSet *Set = new CXStringSet;
Set->Count = Strings.size();
Set->Strings = new CXString[Set->Count];
for (unsigned SI = 0, SE = Set->Count; SI < SE; ++SI)
Set->Strings[SI] = createDup(Strings[SI]);
return Set;
}
//===----------------------------------------------------------------------===//
// String pools.
//===----------------------------------------------------------------------===//
CXStringPool::~CXStringPool() {
for (std::vector<CXStringBuf *>::iterator I = Pool.begin(), E = Pool.end();
I != E; ++I) {
delete *I;
}
}
CXStringBuf *CXStringPool::getCXStringBuf(CXTranslationUnit TU) {
if (Pool.empty())
return new CXStringBuf(TU);
CXStringBuf *Buf = Pool.back();
Buf->Data.clear();
Pool.pop_back();
return Buf;
}
CXStringBuf *getCXStringBuf(CXTranslationUnit TU) {
return TU->StringPool->getCXStringBuf(TU);
}
void CXStringBuf::dispose() {
TU->StringPool->Pool.push_back(this);
}
bool isManagedByPool(CXString str) {
return ((CXStringFlag) str.private_flags) == CXS_StringBuf;
}
} // end namespace cxstring
} // end namespace clang
//===----------------------------------------------------------------------===//
// libClang public APIs.
//===----------------------------------------------------------------------===//
const char *clang_getCString(CXString string) {
if (string.private_flags == (unsigned) CXS_StringBuf) {
return static_cast<const cxstring::CXStringBuf *>(string.data)->Data.data();
}
return static_cast<const char *>(string.data);
}
void clang_disposeString(CXString string) {
switch ((CXStringFlag) string.private_flags) {
case CXS_Unmanaged:
break;
case CXS_Malloc:
if (string.data)
free(const_cast<void *>(string.data));
break;
case CXS_StringBuf:
static_cast<cxstring::CXStringBuf *>(
const_cast<void *>(string.data))->dispose();
break;
}
}
void clang_disposeStringSet(CXStringSet *set) {
for (unsigned SI = 0, SE = set->Count; SI < SE; ++SI)
clang_disposeString(set->Strings[SI]);
delete[] set->Strings;
delete set;
}