CXString.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  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
  11. // CXStrings.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "CXString.h"
  15. #include "CXTranslationUnit.h"
  16. #include "clang-c/Index.h"
  17. #include "clang/Frontend/ASTUnit.h"
  18. #include "llvm/Support/ErrorHandling.h"
  19. using namespace clang;
  20. /// Describes the kind of underlying data in CXString.
  21. enum CXStringFlag {
  22. /// CXString contains a 'const char *' that it doesn't own.
  23. CXS_Unmanaged,
  24. /// CXString contains a 'const char *' that it allocated with malloc().
  25. CXS_Malloc,
  26. /// CXString contains a CXStringBuf that needs to be returned to the
  27. /// CXStringPool.
  28. CXS_StringBuf
  29. };
  30. namespace clang {
  31. namespace cxstring {
  32. //===----------------------------------------------------------------------===//
  33. // Basic generation of CXStrings.
  34. //===----------------------------------------------------------------------===//
  35. CXString createEmpty() {
  36. CXString Str;
  37. Str.data = "";
  38. Str.private_flags = CXS_Unmanaged;
  39. return Str;
  40. }
  41. CXString createNull() {
  42. CXString Str;
  43. Str.data = nullptr;
  44. Str.private_flags = CXS_Unmanaged;
  45. return Str;
  46. }
  47. CXString createRef(const char *String) {
  48. if (String && String[0] == '\0')
  49. return createEmpty();
  50. CXString Str;
  51. Str.data = String;
  52. Str.private_flags = CXS_Unmanaged;
  53. return Str;
  54. }
  55. CXString createDup(const char *String) {
  56. if (!String)
  57. return createNull();
  58. if (String[0] == '\0')
  59. return createEmpty();
  60. CXString Str;
  61. Str.data = strdup(String);
  62. Str.private_flags = CXS_Malloc;
  63. return Str;
  64. }
  65. CXString createRef(StringRef String) {
  66. if (!String.data())
  67. return createNull();
  68. // If the string is empty, it might point to a position in another string
  69. // while having zero length. Make sure we don't create a reference to the
  70. // larger string.
  71. if (String.empty())
  72. return createEmpty();
  73. // If the string is not nul-terminated, we have to make a copy.
  74. // FIXME: This is doing a one past end read, and should be removed! For memory
  75. // we don't manage, the API string can become unterminated at any time outside
  76. // our control.
  77. if (String.data()[String.size()] != 0)
  78. return createDup(String);
  79. CXString Result;
  80. Result.data = String.data();
  81. Result.private_flags = (unsigned) CXS_Unmanaged;
  82. return Result;
  83. }
  84. CXString createDup(StringRef String) {
  85. CXString Result;
  86. char *Spelling = static_cast<char *>(llvm::safe_malloc(String.size() + 1));
  87. memmove(Spelling, String.data(), String.size());
  88. Spelling[String.size()] = 0;
  89. Result.data = Spelling;
  90. Result.private_flags = (unsigned) CXS_Malloc;
  91. return Result;
  92. }
  93. CXString createCXString(CXStringBuf *buf) {
  94. CXString Str;
  95. Str.data = buf;
  96. Str.private_flags = (unsigned) CXS_StringBuf;
  97. return Str;
  98. }
  99. CXStringSet *createSet(const std::vector<std::string> &Strings) {
  100. CXStringSet *Set = new CXStringSet;
  101. Set->Count = Strings.size();
  102. Set->Strings = new CXString[Set->Count];
  103. for (unsigned SI = 0, SE = Set->Count; SI < SE; ++SI)
  104. Set->Strings[SI] = createDup(Strings[SI]);
  105. return Set;
  106. }
  107. //===----------------------------------------------------------------------===//
  108. // String pools.
  109. //===----------------------------------------------------------------------===//
  110. CXStringPool::~CXStringPool() {
  111. for (std::vector<CXStringBuf *>::iterator I = Pool.begin(), E = Pool.end();
  112. I != E; ++I) {
  113. delete *I;
  114. }
  115. }
  116. CXStringBuf *CXStringPool::getCXStringBuf(CXTranslationUnit TU) {
  117. if (Pool.empty())
  118. return new CXStringBuf(TU);
  119. CXStringBuf *Buf = Pool.back();
  120. Buf->Data.clear();
  121. Pool.pop_back();
  122. return Buf;
  123. }
  124. CXStringBuf *getCXStringBuf(CXTranslationUnit TU) {
  125. return TU->StringPool->getCXStringBuf(TU);
  126. }
  127. void CXStringBuf::dispose() {
  128. TU->StringPool->Pool.push_back(this);
  129. }
  130. bool isManagedByPool(CXString str) {
  131. return ((CXStringFlag) str.private_flags) == CXS_StringBuf;
  132. }
  133. } // end namespace cxstring
  134. } // end namespace clang
  135. //===----------------------------------------------------------------------===//
  136. // libClang public APIs.
  137. //===----------------------------------------------------------------------===//
  138. const char *clang_getCString(CXString string) {
  139. if (string.private_flags == (unsigned) CXS_StringBuf) {
  140. return static_cast<const cxstring::CXStringBuf *>(string.data)->Data.data();
  141. }
  142. return static_cast<const char *>(string.data);
  143. }
  144. void clang_disposeString(CXString string) {
  145. switch ((CXStringFlag) string.private_flags) {
  146. case CXS_Unmanaged:
  147. break;
  148. case CXS_Malloc:
  149. if (string.data)
  150. free(const_cast<void *>(string.data));
  151. break;
  152. case CXS_StringBuf:
  153. static_cast<cxstring::CXStringBuf *>(
  154. const_cast<void *>(string.data))->dispose();
  155. break;
  156. }
  157. }
  158. void clang_disposeStringSet(CXStringSet *set) {
  159. for (unsigned SI = 0, SE = set->Count; SI < SE; ++SI)
  160. clang_disposeString(set->Strings[SI]);
  161. delete[] set->Strings;
  162. delete set;
  163. }