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 CharString
&CharString::copyFrom(const CharString
&s
, UErrorCode
&errorCode
) {
39 if(U_SUCCESS(errorCode
) && this!=&s
&& ensureCapacity(s
.len
+1, 0, errorCode
)) {
41 uprv_memcpy(buffer
.getAlias(), s
.buffer
.getAlias(), len
+1);
46 int32_t CharString::lastIndexOf(char c
) const {
47 for(int32_t i
=len
; i
>0;) {
55 CharString
&CharString::truncate(int32_t newLength
) {
60 buffer
[len
=newLength
]=0;
65 CharString
&CharString::append(char c
, UErrorCode
&errorCode
) {
66 if(ensureCapacity(len
+2, 0, errorCode
)) {
73 CharString
&CharString::append(const char *s
, int32_t sLength
, UErrorCode
&errorCode
) {
74 if(U_FAILURE(errorCode
)) {
77 if(sLength
<-1 || (s
==NULL
&& sLength
!=0)) {
78 errorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
82 sLength
= static_cast<int32_t>(uprv_strlen(s
));
85 if(s
==(buffer
.getAlias()+len
)) {
86 // The caller wrote into the getAppendBuffer().
87 if(sLength
>=(buffer
.getCapacity()-len
)) {
88 // The caller wrote too much.
89 errorCode
=U_INTERNAL_PROGRAM_ERROR
;
91 buffer
[len
+=sLength
]=0;
93 } else if(buffer
.getAlias()<=s
&& s
<(buffer
.getAlias()+len
) &&
94 sLength
>=(buffer
.getCapacity()-len
)
96 // (Part of) this string is appended to itself which requires reallocation,
97 // so we have to make a copy of the substring and append that.
98 return append(CharString(s
, sLength
, errorCode
), errorCode
);
99 } else if(ensureCapacity(len
+sLength
+1, 0, errorCode
)) {
100 uprv_memcpy(buffer
.getAlias()+len
, s
, sLength
);
101 buffer
[len
+=sLength
]=0;
107 char *CharString::getAppendBuffer(int32_t minCapacity
,
108 int32_t desiredCapacityHint
,
109 int32_t &resultCapacity
,
110 UErrorCode
&errorCode
) {
111 if(U_FAILURE(errorCode
)) {
115 int32_t appendCapacity
=buffer
.getCapacity()-len
-1; // -1 for NUL
116 if(appendCapacity
>=minCapacity
) {
117 resultCapacity
=appendCapacity
;
118 return buffer
.getAlias()+len
;
120 if(ensureCapacity(len
+minCapacity
+1, len
+desiredCapacityHint
+1, errorCode
)) {
121 resultCapacity
=buffer
.getCapacity()-len
-1;
122 return buffer
.getAlias()+len
;
128 CharString
&CharString::appendInvariantChars(const UnicodeString
&s
, UErrorCode
&errorCode
) {
129 return appendInvariantChars(s
.getBuffer(), s
.length(), errorCode
);
132 CharString
&CharString::appendInvariantChars(const UChar
* uchars
, int32_t ucharsLen
, UErrorCode
&errorCode
) {
133 if(U_FAILURE(errorCode
)) {
136 if (!uprv_isInvariantUString(uchars
, ucharsLen
)) {
137 errorCode
= U_INVARIANT_CONVERSION_ERROR
;
140 if(ensureCapacity(len
+ucharsLen
+1, 0, errorCode
)) {
141 u_UCharsToChars(uchars
, buffer
.getAlias()+len
, ucharsLen
);
148 UBool
CharString::ensureCapacity(int32_t capacity
,
149 int32_t desiredCapacityHint
,
150 UErrorCode
&errorCode
) {
151 if(U_FAILURE(errorCode
)) {
154 if(capacity
>buffer
.getCapacity()) {
155 if(desiredCapacityHint
==0) {
156 desiredCapacityHint
=capacity
+buffer
.getCapacity();
158 if( (desiredCapacityHint
<=capacity
|| buffer
.resize(desiredCapacityHint
, len
+1)==NULL
) &&
159 buffer
.resize(capacity
, len
+1)==NULL
161 errorCode
=U_MEMORY_ALLOCATION_ERROR
;
168 CharString
&CharString::appendPathPart(StringPiece s
, UErrorCode
&errorCode
) {
169 if(U_FAILURE(errorCode
)) {
176 if(len
>0 && (c
=buffer
[len
-1])!=U_FILE_SEP_CHAR
&& c
!=U_FILE_ALT_SEP_CHAR
) {
177 append(U_FILE_SEP_CHAR
, errorCode
);
179 append(s
, errorCode
);
183 CharString
&CharString::ensureEndsWithFileSeparator(UErrorCode
&errorCode
) {
185 if(U_SUCCESS(errorCode
) && len
>0 &&
186 (c
=buffer
[len
-1])!=U_FILE_SEP_CHAR
&& c
!=U_FILE_ALT_SEP_CHAR
) {
187 append(U_FILE_SEP_CHAR
, errorCode
);