11cb0ef41Sopenharmony_ci// © 2016 and later: Unicode, Inc. and others. 21cb0ef41Sopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 31cb0ef41Sopenharmony_ci/* 41cb0ef41Sopenharmony_ci******************************************************************************* 51cb0ef41Sopenharmony_ci* Copyright (C) 2010-2015, International Business Machines 61cb0ef41Sopenharmony_ci* Corporation and others. All Rights Reserved. 71cb0ef41Sopenharmony_ci******************************************************************************* 81cb0ef41Sopenharmony_ci* file name: charstr.cpp 91cb0ef41Sopenharmony_ci* encoding: UTF-8 101cb0ef41Sopenharmony_ci* tab size: 8 (not used) 111cb0ef41Sopenharmony_ci* indentation:4 121cb0ef41Sopenharmony_ci* 131cb0ef41Sopenharmony_ci* created on: 2010may19 141cb0ef41Sopenharmony_ci* created by: Markus W. Scherer 151cb0ef41Sopenharmony_ci*/ 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ci#include <cstdlib> 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci#include "unicode/utypes.h" 201cb0ef41Sopenharmony_ci#include "unicode/putil.h" 211cb0ef41Sopenharmony_ci#include "charstr.h" 221cb0ef41Sopenharmony_ci#include "cmemory.h" 231cb0ef41Sopenharmony_ci#include "cstring.h" 241cb0ef41Sopenharmony_ci#include "uinvchar.h" 251cb0ef41Sopenharmony_ci#include "ustr_imp.h" 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ciU_NAMESPACE_BEGIN 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ciCharString::CharString(CharString&& src) noexcept 301cb0ef41Sopenharmony_ci : buffer(std::move(src.buffer)), len(src.len) { 311cb0ef41Sopenharmony_ci src.len = 0; // not strictly necessary because we make no guarantees on the source string 321cb0ef41Sopenharmony_ci} 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ciCharString& CharString::operator=(CharString&& src) noexcept { 351cb0ef41Sopenharmony_ci buffer = std::move(src.buffer); 361cb0ef41Sopenharmony_ci len = src.len; 371cb0ef41Sopenharmony_ci src.len = 0; // not strictly necessary because we make no guarantees on the source string 381cb0ef41Sopenharmony_ci return *this; 391cb0ef41Sopenharmony_ci} 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_cichar *CharString::cloneData(UErrorCode &errorCode) const { 421cb0ef41Sopenharmony_ci if (U_FAILURE(errorCode)) { return nullptr; } 431cb0ef41Sopenharmony_ci char *p = static_cast<char *>(uprv_malloc(len + 1)); 441cb0ef41Sopenharmony_ci if (p == nullptr) { 451cb0ef41Sopenharmony_ci errorCode = U_MEMORY_ALLOCATION_ERROR; 461cb0ef41Sopenharmony_ci return nullptr; 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci uprv_memcpy(p, buffer.getAlias(), len + 1); 491cb0ef41Sopenharmony_ci return p; 501cb0ef41Sopenharmony_ci} 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ciint32_t CharString::extract(char *dest, int32_t capacity, UErrorCode &errorCode) const { 531cb0ef41Sopenharmony_ci if (U_FAILURE(errorCode)) { return len; } 541cb0ef41Sopenharmony_ci if (capacity < 0 || (capacity > 0 && dest == nullptr)) { 551cb0ef41Sopenharmony_ci errorCode = U_ILLEGAL_ARGUMENT_ERROR; 561cb0ef41Sopenharmony_ci return len; 571cb0ef41Sopenharmony_ci } 581cb0ef41Sopenharmony_ci const char *src = buffer.getAlias(); 591cb0ef41Sopenharmony_ci if (0 < len && len <= capacity && src != dest) { 601cb0ef41Sopenharmony_ci uprv_memcpy(dest, src, len); 611cb0ef41Sopenharmony_ci } 621cb0ef41Sopenharmony_ci return u_terminateChars(dest, capacity, len, &errorCode); 631cb0ef41Sopenharmony_ci} 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ciCharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) { 661cb0ef41Sopenharmony_ci if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) { 671cb0ef41Sopenharmony_ci len=s.len; 681cb0ef41Sopenharmony_ci uprv_memcpy(buffer.getAlias(), s.buffer.getAlias(), len+1); 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci return *this; 711cb0ef41Sopenharmony_ci} 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ciint32_t CharString::lastIndexOf(char c) const { 741cb0ef41Sopenharmony_ci for(int32_t i=len; i>0;) { 751cb0ef41Sopenharmony_ci if(buffer[--i]==c) { 761cb0ef41Sopenharmony_ci return i; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci return -1; 801cb0ef41Sopenharmony_ci} 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_cibool CharString::contains(StringPiece s) const { 831cb0ef41Sopenharmony_ci if (s.empty()) { return false; } 841cb0ef41Sopenharmony_ci const char *p = buffer.getAlias(); 851cb0ef41Sopenharmony_ci int32_t lastStart = len - s.length(); 861cb0ef41Sopenharmony_ci for (int32_t i = 0; i <= lastStart; ++i) { 871cb0ef41Sopenharmony_ci if (uprv_memcmp(p + i, s.data(), s.length()) == 0) { 881cb0ef41Sopenharmony_ci return true; 891cb0ef41Sopenharmony_ci } 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci return false; 921cb0ef41Sopenharmony_ci} 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ciCharString &CharString::truncate(int32_t newLength) { 951cb0ef41Sopenharmony_ci if(newLength<0) { 961cb0ef41Sopenharmony_ci newLength=0; 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci if(newLength<len) { 991cb0ef41Sopenharmony_ci buffer[len=newLength]=0; 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci return *this; 1021cb0ef41Sopenharmony_ci} 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ciCharString &CharString::append(char c, UErrorCode &errorCode) { 1051cb0ef41Sopenharmony_ci if(ensureCapacity(len+2, 0, errorCode)) { 1061cb0ef41Sopenharmony_ci buffer[len++]=c; 1071cb0ef41Sopenharmony_ci buffer[len]=0; 1081cb0ef41Sopenharmony_ci } 1091cb0ef41Sopenharmony_ci return *this; 1101cb0ef41Sopenharmony_ci} 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ciCharString &CharString::append(const char *s, int32_t sLength, UErrorCode &errorCode) { 1131cb0ef41Sopenharmony_ci if(U_FAILURE(errorCode)) { 1141cb0ef41Sopenharmony_ci return *this; 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci if(sLength<-1 || (s==nullptr && sLength!=0)) { 1171cb0ef41Sopenharmony_ci errorCode=U_ILLEGAL_ARGUMENT_ERROR; 1181cb0ef41Sopenharmony_ci return *this; 1191cb0ef41Sopenharmony_ci } 1201cb0ef41Sopenharmony_ci if(sLength<0) { 1211cb0ef41Sopenharmony_ci sLength= static_cast<int32_t>(uprv_strlen(s)); 1221cb0ef41Sopenharmony_ci } 1231cb0ef41Sopenharmony_ci if(sLength>0) { 1241cb0ef41Sopenharmony_ci if(s==(buffer.getAlias()+len)) { 1251cb0ef41Sopenharmony_ci // The caller wrote into the getAppendBuffer(). 1261cb0ef41Sopenharmony_ci if(sLength>=(buffer.getCapacity()-len)) { 1271cb0ef41Sopenharmony_ci // The caller wrote too much. 1281cb0ef41Sopenharmony_ci errorCode=U_INTERNAL_PROGRAM_ERROR; 1291cb0ef41Sopenharmony_ci } else { 1301cb0ef41Sopenharmony_ci buffer[len+=sLength]=0; 1311cb0ef41Sopenharmony_ci } 1321cb0ef41Sopenharmony_ci } else if(buffer.getAlias()<=s && s<(buffer.getAlias()+len) && 1331cb0ef41Sopenharmony_ci sLength>=(buffer.getCapacity()-len) 1341cb0ef41Sopenharmony_ci ) { 1351cb0ef41Sopenharmony_ci // (Part of) this string is appended to itself which requires reallocation, 1361cb0ef41Sopenharmony_ci // so we have to make a copy of the substring and append that. 1371cb0ef41Sopenharmony_ci return append(CharString(s, sLength, errorCode), errorCode); 1381cb0ef41Sopenharmony_ci } else if(ensureCapacity(len+sLength+1, 0, errorCode)) { 1391cb0ef41Sopenharmony_ci uprv_memcpy(buffer.getAlias()+len, s, sLength); 1401cb0ef41Sopenharmony_ci buffer[len+=sLength]=0; 1411cb0ef41Sopenharmony_ci } 1421cb0ef41Sopenharmony_ci } 1431cb0ef41Sopenharmony_ci return *this; 1441cb0ef41Sopenharmony_ci} 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ciCharString &CharString::appendNumber(int32_t number, UErrorCode &status) { 1471cb0ef41Sopenharmony_ci if (number < 0) { 1481cb0ef41Sopenharmony_ci this->append('-', status); 1491cb0ef41Sopenharmony_ci if (U_FAILURE(status)) { 1501cb0ef41Sopenharmony_ci return *this; 1511cb0ef41Sopenharmony_ci } 1521cb0ef41Sopenharmony_ci } 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci if (number == 0) { 1551cb0ef41Sopenharmony_ci this->append('0', status); 1561cb0ef41Sopenharmony_ci return *this; 1571cb0ef41Sopenharmony_ci } 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci int32_t numLen = 0; 1601cb0ef41Sopenharmony_ci while (number != 0) { 1611cb0ef41Sopenharmony_ci int32_t residue = number % 10; 1621cb0ef41Sopenharmony_ci number /= 10; 1631cb0ef41Sopenharmony_ci this->append(std::abs(residue) + '0', status); 1641cb0ef41Sopenharmony_ci numLen++; 1651cb0ef41Sopenharmony_ci if (U_FAILURE(status)) { 1661cb0ef41Sopenharmony_ci return *this; 1671cb0ef41Sopenharmony_ci } 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci int32_t start = this->length() - numLen, end = this->length() - 1; 1711cb0ef41Sopenharmony_ci while(start < end) { 1721cb0ef41Sopenharmony_ci std::swap(this->data()[start++], this->data()[end--]); 1731cb0ef41Sopenharmony_ci } 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci return *this; 1761cb0ef41Sopenharmony_ci} 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_cichar *CharString::getAppendBuffer(int32_t minCapacity, 1791cb0ef41Sopenharmony_ci int32_t desiredCapacityHint, 1801cb0ef41Sopenharmony_ci int32_t &resultCapacity, 1811cb0ef41Sopenharmony_ci UErrorCode &errorCode) { 1821cb0ef41Sopenharmony_ci if(U_FAILURE(errorCode)) { 1831cb0ef41Sopenharmony_ci resultCapacity=0; 1841cb0ef41Sopenharmony_ci return nullptr; 1851cb0ef41Sopenharmony_ci } 1861cb0ef41Sopenharmony_ci int32_t appendCapacity=buffer.getCapacity()-len-1; // -1 for NUL 1871cb0ef41Sopenharmony_ci if(appendCapacity>=minCapacity) { 1881cb0ef41Sopenharmony_ci resultCapacity=appendCapacity; 1891cb0ef41Sopenharmony_ci return buffer.getAlias()+len; 1901cb0ef41Sopenharmony_ci } 1911cb0ef41Sopenharmony_ci if(ensureCapacity(len+minCapacity+1, len+desiredCapacityHint+1, errorCode)) { 1921cb0ef41Sopenharmony_ci resultCapacity=buffer.getCapacity()-len-1; 1931cb0ef41Sopenharmony_ci return buffer.getAlias()+len; 1941cb0ef41Sopenharmony_ci } 1951cb0ef41Sopenharmony_ci resultCapacity=0; 1961cb0ef41Sopenharmony_ci return nullptr; 1971cb0ef41Sopenharmony_ci} 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ciCharString &CharString::appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode) { 2001cb0ef41Sopenharmony_ci return appendInvariantChars(s.getBuffer(), s.length(), errorCode); 2011cb0ef41Sopenharmony_ci} 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ciCharString &CharString::appendInvariantChars(const char16_t* uchars, int32_t ucharsLen, UErrorCode &errorCode) { 2041cb0ef41Sopenharmony_ci if(U_FAILURE(errorCode)) { 2051cb0ef41Sopenharmony_ci return *this; 2061cb0ef41Sopenharmony_ci } 2071cb0ef41Sopenharmony_ci if (!uprv_isInvariantUString(uchars, ucharsLen)) { 2081cb0ef41Sopenharmony_ci errorCode = U_INVARIANT_CONVERSION_ERROR; 2091cb0ef41Sopenharmony_ci return *this; 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci if(ensureCapacity(len+ucharsLen+1, 0, errorCode)) { 2121cb0ef41Sopenharmony_ci u_UCharsToChars(uchars, buffer.getAlias()+len, ucharsLen); 2131cb0ef41Sopenharmony_ci len += ucharsLen; 2141cb0ef41Sopenharmony_ci buffer[len] = 0; 2151cb0ef41Sopenharmony_ci } 2161cb0ef41Sopenharmony_ci return *this; 2171cb0ef41Sopenharmony_ci} 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ciUBool CharString::ensureCapacity(int32_t capacity, 2201cb0ef41Sopenharmony_ci int32_t desiredCapacityHint, 2211cb0ef41Sopenharmony_ci UErrorCode &errorCode) { 2221cb0ef41Sopenharmony_ci if(U_FAILURE(errorCode)) { 2231cb0ef41Sopenharmony_ci return false; 2241cb0ef41Sopenharmony_ci } 2251cb0ef41Sopenharmony_ci if(capacity>buffer.getCapacity()) { 2261cb0ef41Sopenharmony_ci if(desiredCapacityHint==0) { 2271cb0ef41Sopenharmony_ci desiredCapacityHint=capacity+buffer.getCapacity(); 2281cb0ef41Sopenharmony_ci } 2291cb0ef41Sopenharmony_ci if( (desiredCapacityHint<=capacity || buffer.resize(desiredCapacityHint, len+1)==nullptr) && 2301cb0ef41Sopenharmony_ci buffer.resize(capacity, len+1)==nullptr 2311cb0ef41Sopenharmony_ci ) { 2321cb0ef41Sopenharmony_ci errorCode=U_MEMORY_ALLOCATION_ERROR; 2331cb0ef41Sopenharmony_ci return false; 2341cb0ef41Sopenharmony_ci } 2351cb0ef41Sopenharmony_ci } 2361cb0ef41Sopenharmony_ci return true; 2371cb0ef41Sopenharmony_ci} 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ciCharString &CharString::appendPathPart(StringPiece s, UErrorCode &errorCode) { 2401cb0ef41Sopenharmony_ci if(U_FAILURE(errorCode)) { 2411cb0ef41Sopenharmony_ci return *this; 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci if(s.length()==0) { 2441cb0ef41Sopenharmony_ci return *this; 2451cb0ef41Sopenharmony_ci } 2461cb0ef41Sopenharmony_ci char c; 2471cb0ef41Sopenharmony_ci if(len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) { 2481cb0ef41Sopenharmony_ci append(getDirSepChar(), errorCode); 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci append(s, errorCode); 2511cb0ef41Sopenharmony_ci return *this; 2521cb0ef41Sopenharmony_ci} 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ciCharString &CharString::ensureEndsWithFileSeparator(UErrorCode &errorCode) { 2551cb0ef41Sopenharmony_ci char c; 2561cb0ef41Sopenharmony_ci if(U_SUCCESS(errorCode) && len>0 && 2571cb0ef41Sopenharmony_ci (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) { 2581cb0ef41Sopenharmony_ci append(getDirSepChar(), errorCode); 2591cb0ef41Sopenharmony_ci } 2601cb0ef41Sopenharmony_ci return *this; 2611cb0ef41Sopenharmony_ci} 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_cichar CharString::getDirSepChar() const { 2641cb0ef41Sopenharmony_ci char dirSepChar = U_FILE_SEP_CHAR; 2651cb0ef41Sopenharmony_ci#if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR) 2661cb0ef41Sopenharmony_ci // We may need to return a different directory separator when building for Cygwin or MSYS2. 2671cb0ef41Sopenharmony_ci if(len>0 && !uprv_strchr(data(), U_FILE_SEP_CHAR) && uprv_strchr(data(), U_FILE_ALT_SEP_CHAR)) 2681cb0ef41Sopenharmony_ci dirSepChar = U_FILE_ALT_SEP_CHAR; 2691cb0ef41Sopenharmony_ci#endif 2701cb0ef41Sopenharmony_ci return dirSepChar; 2711cb0ef41Sopenharmony_ci} 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ciU_NAMESPACE_END 274