charstr.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // © 2016 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. /*
  4. *******************************************************************************
  5. * Copyright (C) 2010-2015, International Business Machines
  6. * Corporation and others. All Rights Reserved.
  7. *******************************************************************************
  8. * file name: charstr.cpp
  9. * encoding: UTF-8
  10. * tab size: 8 (not used)
  11. * indentation:4
  12. *
  13. * created on: 2010may19
  14. * created by: Markus W. Scherer
  15. */
  16. #include <cstdlib>
  17. #include "unicode/utypes.h"
  18. #include "unicode/putil.h"
  19. #include "charstr.h"
  20. #include "cmemory.h"
  21. #include "cstring.h"
  22. #include "uinvchar.h"
  23. #include "ustr_imp.h"
  24. U_NAMESPACE_BEGIN
  25. CharString::CharString(CharString&& src) noexcept
  26. : buffer(std::move(src.buffer)), len(src.len) {
  27. src.len = 0; // not strictly necessary because we make no guarantees on the source string
  28. }
  29. CharString& CharString::operator=(CharString&& src) noexcept {
  30. buffer = std::move(src.buffer);
  31. len = src.len;
  32. src.len = 0; // not strictly necessary because we make no guarantees on the source string
  33. return *this;
  34. }
  35. char *CharString::cloneData(UErrorCode &errorCode) const {
  36. if (U_FAILURE(errorCode)) { return nullptr; }
  37. char *p = static_cast<char *>(uprv_malloc(len + 1));
  38. if (p == nullptr) {
  39. errorCode = U_MEMORY_ALLOCATION_ERROR;
  40. return nullptr;
  41. }
  42. uprv_memcpy(p, buffer.getAlias(), len + 1);
  43. return p;
  44. }
  45. int32_t CharString::extract(char *dest, int32_t capacity, UErrorCode &errorCode) const {
  46. if (U_FAILURE(errorCode)) { return len; }
  47. if (capacity < 0 || (capacity > 0 && dest == nullptr)) {
  48. errorCode = U_ILLEGAL_ARGUMENT_ERROR;
  49. return len;
  50. }
  51. const char *src = buffer.getAlias();
  52. if (0 < len && len <= capacity && src != dest) {
  53. uprv_memcpy(dest, src, len);
  54. }
  55. return u_terminateChars(dest, capacity, len, &errorCode);
  56. }
  57. CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) {
  58. if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) {
  59. len=s.len;
  60. uprv_memcpy(buffer.getAlias(), s.buffer.getAlias(), len+1);
  61. }
  62. return *this;
  63. }
  64. int32_t CharString::lastIndexOf(char c) const {
  65. for(int32_t i=len; i>0;) {
  66. if(buffer[--i]==c) {
  67. return i;
  68. }
  69. }
  70. return -1;
  71. }
  72. bool CharString::contains(StringPiece s) const {
  73. if (s.empty()) { return false; }
  74. const char *p = buffer.getAlias();
  75. int32_t lastStart = len - s.length();
  76. for (int32_t i = 0; i <= lastStart; ++i) {
  77. if (uprv_memcmp(p + i, s.data(), s.length()) == 0) {
  78. return true;
  79. }
  80. }
  81. return false;
  82. }
  83. CharString &CharString::truncate(int32_t newLength) {
  84. if(newLength<0) {
  85. newLength=0;
  86. }
  87. if(newLength<len) {
  88. buffer[len=newLength]=0;
  89. }
  90. return *this;
  91. }
  92. CharString &CharString::append(char c, UErrorCode &errorCode) {
  93. if(ensureCapacity(len+2, 0, errorCode)) {
  94. buffer[len++]=c;
  95. buffer[len]=0;
  96. }
  97. return *this;
  98. }
  99. CharString &CharString::append(const char *s, int32_t sLength, UErrorCode &errorCode) {
  100. if(U_FAILURE(errorCode)) {
  101. return *this;
  102. }
  103. if(sLength<-1 || (s==nullptr && sLength!=0)) {
  104. errorCode=U_ILLEGAL_ARGUMENT_ERROR;
  105. return *this;
  106. }
  107. if(sLength<0) {
  108. sLength= static_cast<int32_t>(uprv_strlen(s));
  109. }
  110. if(sLength>0) {
  111. if(s==(buffer.getAlias()+len)) {
  112. // The caller wrote into the getAppendBuffer().
  113. if(sLength>=(buffer.getCapacity()-len)) {
  114. // The caller wrote too much.
  115. errorCode=U_INTERNAL_PROGRAM_ERROR;
  116. } else {
  117. buffer[len+=sLength]=0;
  118. }
  119. } else if(buffer.getAlias()<=s && s<(buffer.getAlias()+len) &&
  120. sLength>=(buffer.getCapacity()-len)
  121. ) {
  122. // (Part of) this string is appended to itself which requires reallocation,
  123. // so we have to make a copy of the substring and append that.
  124. return append(CharString(s, sLength, errorCode), errorCode);
  125. } else if(ensureCapacity(len+sLength+1, 0, errorCode)) {
  126. uprv_memcpy(buffer.getAlias()+len, s, sLength);
  127. buffer[len+=sLength]=0;
  128. }
  129. }
  130. return *this;
  131. }
  132. CharString &CharString::appendNumber(int32_t number, UErrorCode &status) {
  133. if (number < 0) {
  134. this->append('-', status);
  135. if (U_FAILURE(status)) {
  136. return *this;
  137. }
  138. }
  139. if (number == 0) {
  140. this->append('0', status);
  141. return *this;
  142. }
  143. int32_t numLen = 0;
  144. while (number != 0) {
  145. int32_t residue = number % 10;
  146. number /= 10;
  147. this->append(std::abs(residue) + '0', status);
  148. numLen++;
  149. if (U_FAILURE(status)) {
  150. return *this;
  151. }
  152. }
  153. int32_t start = this->length() - numLen, end = this->length() - 1;
  154. while(start < end) {
  155. std::swap(this->data()[start++], this->data()[end--]);
  156. }
  157. return *this;
  158. }
  159. char *CharString::getAppendBuffer(int32_t minCapacity,
  160. int32_t desiredCapacityHint,
  161. int32_t &resultCapacity,
  162. UErrorCode &errorCode) {
  163. if(U_FAILURE(errorCode)) {
  164. resultCapacity=0;
  165. return nullptr;
  166. }
  167. int32_t appendCapacity=buffer.getCapacity()-len-1; // -1 for NUL
  168. if(appendCapacity>=minCapacity) {
  169. resultCapacity=appendCapacity;
  170. return buffer.getAlias()+len;
  171. }
  172. if(ensureCapacity(len+minCapacity+1, len+desiredCapacityHint+1, errorCode)) {
  173. resultCapacity=buffer.getCapacity()-len-1;
  174. return buffer.getAlias()+len;
  175. }
  176. resultCapacity=0;
  177. return nullptr;
  178. }
  179. CharString &CharString::appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode) {
  180. return appendInvariantChars(s.getBuffer(), s.length(), errorCode);
  181. }
  182. CharString &CharString::appendInvariantChars(const char16_t* uchars, int32_t ucharsLen, UErrorCode &errorCode) {
  183. if(U_FAILURE(errorCode)) {
  184. return *this;
  185. }
  186. if (!uprv_isInvariantUString(uchars, ucharsLen)) {
  187. errorCode = U_INVARIANT_CONVERSION_ERROR;
  188. return *this;
  189. }
  190. if(ensureCapacity(len+ucharsLen+1, 0, errorCode)) {
  191. u_UCharsToChars(uchars, buffer.getAlias()+len, ucharsLen);
  192. len += ucharsLen;
  193. buffer[len] = 0;
  194. }
  195. return *this;
  196. }
  197. UBool CharString::ensureCapacity(int32_t capacity,
  198. int32_t desiredCapacityHint,
  199. UErrorCode &errorCode) {
  200. if(U_FAILURE(errorCode)) {
  201. return false;
  202. }
  203. if(capacity>buffer.getCapacity()) {
  204. if(desiredCapacityHint==0) {
  205. desiredCapacityHint=capacity+buffer.getCapacity();
  206. }
  207. if( (desiredCapacityHint<=capacity || buffer.resize(desiredCapacityHint, len+1)==nullptr) &&
  208. buffer.resize(capacity, len+1)==nullptr
  209. ) {
  210. errorCode=U_MEMORY_ALLOCATION_ERROR;
  211. return false;
  212. }
  213. }
  214. return true;
  215. }
  216. CharString &CharString::appendPathPart(StringPiece s, UErrorCode &errorCode) {
  217. if(U_FAILURE(errorCode)) {
  218. return *this;
  219. }
  220. if(s.length()==0) {
  221. return *this;
  222. }
  223. char c;
  224. if(len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
  225. append(getDirSepChar(), errorCode);
  226. }
  227. append(s, errorCode);
  228. return *this;
  229. }
  230. CharString &CharString::ensureEndsWithFileSeparator(UErrorCode &errorCode) {
  231. char c;
  232. if(U_SUCCESS(errorCode) && len>0 &&
  233. (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
  234. append(getDirSepChar(), errorCode);
  235. }
  236. return *this;
  237. }
  238. char CharString::getDirSepChar() const {
  239. char dirSepChar = U_FILE_SEP_CHAR;
  240. #if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
  241. // We may need to return a different directory separator when building for Cygwin or MSYS2.
  242. if(len>0 && !uprv_strchr(data(), U_FILE_SEP_CHAR) && uprv_strchr(data(), U_FILE_ALT_SEP_CHAR))
  243. dirSepChar = U_FILE_ALT_SEP_CHAR;
  244. #endif
  245. return dirSepChar;
  246. }
  247. U_NAMESPACE_END