CXString.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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 the string is not nul-terminated, we have to make a copy.
  67. // FIXME: This is doing a one past end read, and should be removed! For memory
  68. // we don't manage, the API string can become unterminated at any time outside
  69. // our control.
  70. if (!String.empty() && String.data()[String.size()] != 0)
  71. return createDup(String);
  72. CXString Result;
  73. Result.data = String.data();
  74. Result.private_flags = (unsigned) CXS_Unmanaged;
  75. return Result;
  76. }
  77. CXString createDup(StringRef String) {
  78. CXString Result;
  79. char *Spelling = static_cast<char *>(llvm::safe_malloc(String.size() + 1));
  80. memmove(Spelling, String.data(), String.size());
  81. Spelling[String.size()] = 0;
  82. Result.data = Spelling;
  83. Result.private_flags = (unsigned) CXS_Malloc;
  84. return Result;
  85. }
  86. CXString createCXString(CXStringBuf *buf) {
  87. CXString Str;
  88. Str.data = buf;
  89. Str.private_flags = (unsigned) CXS_StringBuf;
  90. return Str;
  91. }
  92. CXStringSet *createSet(const std::vector<std::string> &Strings) {
  93. CXStringSet *Set = new CXStringSet;
  94. Set->Count = Strings.size();
  95. Set->Strings = new CXString[Set->Count];
  96. for (unsigned SI = 0, SE = Set->Count; SI < SE; ++SI)
  97. Set->Strings[SI] = createDup(Strings[SI]);
  98. return Set;
  99. }
  100. //===----------------------------------------------------------------------===//
  101. // String pools.
  102. //===----------------------------------------------------------------------===//
  103. CXStringPool::~CXStringPool() {
  104. for (std::vector<CXStringBuf *>::iterator I = Pool.begin(), E = Pool.end();
  105. I != E; ++I) {
  106. delete *I;
  107. }
  108. }
  109. CXStringBuf *CXStringPool::getCXStringBuf(CXTranslationUnit TU) {
  110. if (Pool.empty())
  111. return new CXStringBuf(TU);
  112. CXStringBuf *Buf = Pool.back();
  113. Buf->Data.clear();
  114. Pool.pop_back();
  115. return Buf;
  116. }
  117. CXStringBuf *getCXStringBuf(CXTranslationUnit TU) {
  118. return TU->StringPool->getCXStringBuf(TU);
  119. }
  120. void CXStringBuf::dispose() {
  121. TU->StringPool->Pool.push_back(this);
  122. }
  123. bool isManagedByPool(CXString str) {
  124. return ((CXStringFlag) str.private_flags) == CXS_StringBuf;
  125. }
  126. } // end namespace cxstring
  127. } // end namespace clang
  128. //===----------------------------------------------------------------------===//
  129. // libClang public APIs.
  130. //===----------------------------------------------------------------------===//
  131. const char *clang_getCString(CXString string) {
  132. if (string.private_flags == (unsigned) CXS_StringBuf) {
  133. return static_cast<const cxstring::CXStringBuf *>(string.data)->Data.data();
  134. }
  135. return static_cast<const char *>(string.data);
  136. }
  137. void clang_disposeString(CXString string) {
  138. switch ((CXStringFlag) string.private_flags) {
  139. case CXS_Unmanaged:
  140. break;
  141. case CXS_Malloc:
  142. if (string.data)
  143. free(const_cast<void *>(string.data));
  144. break;
  145. case CXS_StringBuf:
  146. static_cast<cxstring::CXStringBuf *>(
  147. const_cast<void *>(string.data))->dispose();
  148. break;
  149. }
  150. }
  151. void clang_disposeStringSet(CXStringSet *set) {
  152. for (unsigned SI = 0, SE = set->Count; SI < SE; ++SI)
  153. clang_disposeString(set->Strings[SI]);
  154. delete[] set->Strings;
  155. delete set;
  156. }