blob: dec8ebcd98e147db41230908badc4e1f01fd57f3 [file] [log] [blame]
Ted Kremenekea834df2010-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 Kremenek0a90d322010-11-17 23:24:11 +000017#include "CXTranslationUnit.h"
Ted Kremenekea834df2010-11-16 02:03:55 +000018#include "clang-c/Index.h"
Chandler Carruthf59edb92012-12-04 09:25:21 +000019#include "clang/Frontend/ASTUnit.h"
Ted Kremeneka60ed472010-11-16 08:15:36 +000020#include "llvm/ADT/SmallString.h"
Ted Kremenekea834df2010-11-16 02:03:55 +000021#include "llvm/Support/ErrorHandling.h"
22
23using namespace clang;
Ted Kremenekea834df2010-11-16 02:03:55 +000024
Dmitri Gribenko17c1a242013-02-01 16:36:31 +000025/// Describes the kind of underlying data in CXString.
26enum CXStringFlag {
27 /// CXString contains a 'const char *' that it doesn't own.
28 CXS_Unmanaged,
29
30 /// CXString contains a 'const char *' that it allocated with malloc().
31 CXS_Malloc,
32
33 /// CXString contains a CXStringBuf that needs to be returned to the
34 /// CXStringPool.
35 CXS_StringBuf
36};
Ted Kremeneka60ed472010-11-16 08:15:36 +000037
Dmitri Gribenkof06faad2013-02-03 13:54:26 +000038namespace clang {
39namespace cxstring {
40
Ted Kremeneka60ed472010-11-16 08:15:36 +000041//===----------------------------------------------------------------------===//
42// Basic generation of CXStrings.
43//===----------------------------------------------------------------------===//
Ted Kremenekea834df2010-11-16 02:03:55 +000044
Dmitri Gribenkof06faad2013-02-03 13:54:26 +000045CXString createEmpty() {
Dmitri Gribenkodc66adb2013-02-01 14:21:22 +000046 CXString Str;
47 Str.data = "";
48 Str.private_flags = CXS_Unmanaged;
49 return Str;
50}
51
Dmitri Gribenkof06faad2013-02-03 13:54:26 +000052CXString createNull() {
Dmitri Gribenkodad4c1a2013-02-01 14:13:32 +000053 CXString Str;
Stephen Hinesc568f1e2014-07-21 00:47:37 -070054 Str.data = nullptr;
Dmitri Gribenkodad4c1a2013-02-01 14:13:32 +000055 Str.private_flags = CXS_Unmanaged;
56 return Str;
57}
58
Dmitri Gribenkof06faad2013-02-03 13:54:26 +000059CXString createRef(const char *String) {
Dmitri Gribenko0c4394c2013-02-02 00:02:12 +000060 if (String && String[0] == '\0')
Dmitri Gribenkof06faad2013-02-03 13:54:26 +000061 return createEmpty();
Dmitri Gribenko0c4394c2013-02-02 00:02:12 +000062
Ted Kremenekea834df2010-11-16 02:03:55 +000063 CXString Str;
Dmitri Gribenko0c4394c2013-02-02 00:02:12 +000064 Str.data = String;
65 Str.private_flags = CXS_Unmanaged;
66 return Str;
67}
68
Dmitri Gribenkof06faad2013-02-03 13:54:26 +000069CXString createDup(const char *String) {
Dmitri Gribenko0c4394c2013-02-02 00:02:12 +000070 if (!String)
Dmitri Gribenkof06faad2013-02-03 13:54:26 +000071 return createNull();
Dmitri Gribenko0c4394c2013-02-02 00:02:12 +000072
73 if (String[0] == '\0')
Dmitri Gribenkof06faad2013-02-03 13:54:26 +000074 return createEmpty();
Dmitri Gribenko0c4394c2013-02-02 00:02:12 +000075
76 CXString Str;
77 Str.data = strdup(String);
78 Str.private_flags = CXS_Malloc;
Ted Kremenekea834df2010-11-16 02:03:55 +000079 return Str;
80}
81
Dmitri Gribenkof06faad2013-02-03 13:54:26 +000082CXString createRef(StringRef String) {
Dmitri Gribenko5595ded2013-02-02 02:19:29 +000083 // If the string is not nul-terminated, we have to make a copy.
Stephen Hinesc568f1e2014-07-21 00:47:37 -070084
85 // FIXME: This is doing a one past end read, and should be removed! For memory
86 // we don't manage, the API string can become unterminated at any time outside
87 // our control.
88
Dmitri Gribenko5595ded2013-02-02 02:19:29 +000089 if (!String.empty() && String.data()[String.size()] != 0)
Dmitri Gribenkof06faad2013-02-03 13:54:26 +000090 return createDup(String);
Dmitri Gribenko5595ded2013-02-02 02:19:29 +000091
Ted Kremenekea834df2010-11-16 02:03:55 +000092 CXString Result;
Dmitri Gribenko5595ded2013-02-02 02:19:29 +000093 Result.data = String.data();
94 Result.private_flags = (unsigned) CXS_Unmanaged;
95 return Result;
96}
97
Dmitri Gribenkof06faad2013-02-03 13:54:26 +000098CXString createDup(StringRef String) {
Dmitri Gribenko5595ded2013-02-02 02:19:29 +000099 CXString Result;
100 char *Spelling = static_cast<char *>(malloc(String.size() + 1));
101 memmove(Spelling, String.data(), String.size());
102 Spelling[String.size()] = 0;
103 Result.data = Spelling;
104 Result.private_flags = (unsigned) CXS_Malloc;
Ted Kremenekea834df2010-11-16 02:03:55 +0000105 return Result;
106}
107
Dmitri Gribenkof06faad2013-02-03 13:54:26 +0000108CXString createCXString(CXStringBuf *buf) {
Ted Kremeneka60ed472010-11-16 08:15:36 +0000109 CXString Str;
110 Str.data = buf;
111 Str.private_flags = (unsigned) CXS_StringBuf;
112 return Str;
113}
114
115
116//===----------------------------------------------------------------------===//
117// String pools.
118//===----------------------------------------------------------------------===//
119
Dmitri Gribenkof06faad2013-02-03 13:54:26 +0000120CXStringPool::~CXStringPool() {
Dmitri Gribenko9c48d162013-01-26 22:44:19 +0000121 for (std::vector<CXStringBuf *>::iterator I = Pool.begin(), E = Pool.end();
122 I != E; ++I) {
123 delete *I;
Ted Kremeneka60ed472010-11-16 08:15:36 +0000124 }
125}
126
Dmitri Gribenkof06faad2013-02-03 13:54:26 +0000127CXStringBuf *CXStringPool::getCXStringBuf(CXTranslationUnit TU) {
Dmitri Gribenko9c48d162013-01-26 22:44:19 +0000128 if (Pool.empty())
Ted Kremeneka60ed472010-11-16 08:15:36 +0000129 return new CXStringBuf(TU);
Dmitri Gribenko9c48d162013-01-26 22:44:19 +0000130
131 CXStringBuf *Buf = Pool.back();
132 Buf->Data.clear();
133 Pool.pop_back();
134 return Buf;
Ted Kremeneka60ed472010-11-16 08:15:36 +0000135}
136
Dmitri Gribenkof06faad2013-02-03 13:54:26 +0000137CXStringBuf *getCXStringBuf(CXTranslationUnit TU) {
Dmitri Gribenko9c48d162013-01-26 22:44:19 +0000138 return TU->StringPool->getCXStringBuf(TU);
139}
140
Dmitri Gribenkof06faad2013-02-03 13:54:26 +0000141void CXStringBuf::dispose() {
Dmitri Gribenko9c48d162013-01-26 22:44:19 +0000142 TU->StringPool->Pool.push_back(this);
Ted Kremeneka60ed472010-11-16 08:15:36 +0000143}
144
Dmitri Gribenkof06faad2013-02-03 13:54:26 +0000145bool isManagedByPool(CXString str) {
Ted Kremenekbaf82b02011-08-17 22:19:53 +0000146 return ((CXStringFlag) str.private_flags) == CXS_StringBuf;
147}
148
Dmitri Gribenkof06faad2013-02-03 13:54:26 +0000149} // end namespace cxstring
150} // end namespace clang
151
Ted Kremenekea834df2010-11-16 02:03:55 +0000152//===----------------------------------------------------------------------===//
153// libClang public APIs.
154//===----------------------------------------------------------------------===//
155
156extern "C" {
157const char *clang_getCString(CXString string) {
Ted Kremeneka60ed472010-11-16 08:15:36 +0000158 if (string.private_flags == (unsigned) CXS_StringBuf) {
Dmitri Gribenkof06faad2013-02-03 13:54:26 +0000159 return static_cast<const cxstring::CXStringBuf *>(string.data)->Data.data();
Ted Kremeneka60ed472010-11-16 08:15:36 +0000160 }
Dmitri Gribenkoe358fd52013-01-11 23:13:36 +0000161 return static_cast<const char *>(string.data);
Ted Kremenekea834df2010-11-16 02:03:55 +0000162}
163
164void clang_disposeString(CXString string) {
Ted Kremeneka60ed472010-11-16 08:15:36 +0000165 switch ((CXStringFlag) string.private_flags) {
166 case CXS_Unmanaged:
167 break;
168 case CXS_Malloc:
169 if (string.data)
Dmitri Gribenko689d7472013-01-11 23:08:18 +0000170 free(const_cast<void *>(string.data));
Ted Kremeneka60ed472010-11-16 08:15:36 +0000171 break;
172 case CXS_StringBuf:
Dmitri Gribenkof06faad2013-02-03 13:54:26 +0000173 static_cast<cxstring::CXStringBuf *>(
Dmitri Gribenko9c48d162013-01-26 22:44:19 +0000174 const_cast<void *>(string.data))->dispose();
Ted Kremeneka60ed472010-11-16 08:15:36 +0000175 break;
176 }
Ted Kremenekea834df2010-11-16 02:03:55 +0000177}
178} // end: extern "C"
179