f4a2713ac8
Change-Id: Ia40e9ffdf29b5dab2f122f673ff6802a58bc690f
175 lines
4.5 KiB
C++
175 lines
4.5 KiB
C++
//===- CXString.cpp - Routines for manipulating CXStrings -----------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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/ADT/SmallString.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 = 0;
|
|
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.
|
|
// This is doing a one past end read, and should be removed!
|
|
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 *>(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;
|
|
}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// 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.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
extern "C" {
|
|
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;
|
|
}
|
|
}
|
|
} // end: extern "C"
|
|
|