1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 2010-2015, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * file name: charstr.cpp
10 * tab size: 8 (not used)
13 * created on: 2010may19
14 * created by: Markus W. Scherer
17 #include "unicode/utypes.h"
18 #include "unicode/putil.h"
26 CharString::CharString(CharString
&& src
) U_NOEXCEPT
27 : buffer(std::move(src
.buffer
)), len(src
.len
) {
28 src
.len
= 0; // not strictly necessary because we make no guarantees on the source string
31 CharString
& CharString::operator=(CharString
&& src
) U_NOEXCEPT
{
32 buffer
= std::move(src
.buffer
);
34 src
.len
= 0; // not strictly necessary because we make no guarantees on the source string
38 char *CharString::cloneData(UErrorCode
&errorCode
) const {
39 if (U_FAILURE(errorCode
)) { return nullptr; }
40 char *p
= static_cast<char *>(uprv_malloc(len
+ 1));
42 errorCode
= U_MEMORY_ALLOCATION_ERROR
;
45 uprv_memcpy(p
, buffer
.getAlias(), len
+ 1);
49 CharString
&CharString::copyFrom(const CharString
&s
, UErrorCode
&errorCode
) {
50 if(U_SUCCESS(errorCode
) && this!=&s
&& ensureCapacity(s
.len
+1, 0, errorCode
)) {
52 uprv_memcpy(buffer
.getAlias(), s
.buffer
.getAlias(), len
+1);
57 int32_t CharString::lastIndexOf(char c
) const {
58 for(int32_t i
=len
; i
>0;) {
66 bool CharString::contains(StringPiece s
) const {
67 if (s
.empty()) { return false; }
68 const char *p
= buffer
.getAlias();
69 int32_t lastStart
= len
- s
.length();
70 for (int32_t i
= 0; i
<= lastStart
; ++i
) {
71 if (uprv_memcmp(p
+ i
, s
.data(), s
.length()) == 0) {
78 CharString
&CharString::truncate(int32_t newLength
) {
83 buffer
[len
=newLength
]=0;
88 CharString
&CharString::append(char c
, UErrorCode
&errorCode
) {
89 if(ensureCapacity(len
+2, 0, errorCode
)) {
96 CharString
&CharString::append(const char *s
, int32_t sLength
, UErrorCode
&errorCode
) {
97 if(U_FAILURE(errorCode
)) {
100 if(sLength
<-1 || (s
==NULL
&& sLength
!=0)) {
101 errorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
105 sLength
= static_cast<int32_t>(uprv_strlen(s
));
108 if(s
==(buffer
.getAlias()+len
)) {
109 // The caller wrote into the getAppendBuffer().
110 if(sLength
>=(buffer
.getCapacity()-len
)) {
111 // The caller wrote too much.
112 errorCode
=U_INTERNAL_PROGRAM_ERROR
;
114 buffer
[len
+=sLength
]=0;
116 } else if(buffer
.getAlias()<=s
&& s
<(buffer
.getAlias()+len
) &&
117 sLength
>=(buffer
.getCapacity()-len
)
119 // (Part of) this string is appended to itself which requires reallocation,
120 // so we have to make a copy of the substring and append that.
121 return append(CharString(s
, sLength
, errorCode
), errorCode
);
122 } else if(ensureCapacity(len
+sLength
+1, 0, errorCode
)) {
123 uprv_memcpy(buffer
.getAlias()+len
, s
, sLength
);
124 buffer
[len
+=sLength
]=0;
130 char *CharString::getAppendBuffer(int32_t minCapacity
,
131 int32_t desiredCapacityHint
,
132 int32_t &resultCapacity
,
133 UErrorCode
&errorCode
) {
134 if(U_FAILURE(errorCode
)) {
138 int32_t appendCapacity
=buffer
.getCapacity()-len
-1; // -1 for NUL
139 if(appendCapacity
>=minCapacity
) {
140 resultCapacity
=appendCapacity
;
141 return buffer
.getAlias()+len
;
143 if(ensureCapacity(len
+minCapacity
+1, len
+desiredCapacityHint
+1, errorCode
)) {
144 resultCapacity
=buffer
.getCapacity()-len
-1;
145 return buffer
.getAlias()+len
;
151 CharString
&CharString::appendInvariantChars(const UnicodeString
&s
, UErrorCode
&errorCode
) {
152 return appendInvariantChars(s
.getBuffer(), s
.length(), errorCode
);
155 CharString
&CharString::appendInvariantChars(const UChar
* uchars
, int32_t ucharsLen
, UErrorCode
&errorCode
) {
156 if(U_FAILURE(errorCode
)) {
159 if (!uprv_isInvariantUString(uchars
, ucharsLen
)) {
160 errorCode
= U_INVARIANT_CONVERSION_ERROR
;
163 if(ensureCapacity(len
+ucharsLen
+1, 0, errorCode
)) {
164 u_UCharsToChars(uchars
, buffer
.getAlias()+len
, ucharsLen
);
171 UBool
CharString::ensureCapacity(int32_t capacity
,
172 int32_t desiredCapacityHint
,
173 UErrorCode
&errorCode
) {
174 if(U_FAILURE(errorCode
)) {
177 if(capacity
>buffer
.getCapacity()) {
178 if(desiredCapacityHint
==0) {
179 desiredCapacityHint
=capacity
+buffer
.getCapacity();
181 if( (desiredCapacityHint
<=capacity
|| buffer
.resize(desiredCapacityHint
, len
+1)==NULL
) &&
182 buffer
.resize(capacity
, len
+1)==NULL
184 errorCode
=U_MEMORY_ALLOCATION_ERROR
;
191 CharString
&CharString::appendPathPart(StringPiece s
, UErrorCode
&errorCode
) {
192 if(U_FAILURE(errorCode
)) {
199 if(len
>0 && (c
=buffer
[len
-1])!=U_FILE_SEP_CHAR
&& c
!=U_FILE_ALT_SEP_CHAR
) {
200 append(U_FILE_SEP_CHAR
, errorCode
);
202 append(s
, errorCode
);
206 CharString
&CharString::ensureEndsWithFileSeparator(UErrorCode
&errorCode
) {
208 if(U_SUCCESS(errorCode
) && len
>0 &&
209 (c
=buffer
[len
-1])!=U_FILE_SEP_CHAR
&& c
!=U_FILE_ALT_SEP_CHAR
) {
210 append(U_FILE_SEP_CHAR
, errorCode
);