1 // Copyright (C) 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: US-ASCII
10 * tab size: 8 (not used)
11 * indentation:4
12 *
13 * created on: 2010may19
14 * created by: Markus W. Scherer
15 */
16
17 #include "unicode/utypes.h"
18 #include "charstr.h"
19 #include "cmemory.h"
20 #include "cstring.h"
21 #include "uinvchar.h"
22
23 U_NAMESPACE_BEGIN
24
copyFrom(const CharString & s,UErrorCode & errorCode)25 CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) {
26 if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) {
27 len=s.len;
28 uprv_memcpy(buffer.getAlias(), s.buffer.getAlias(), len+1);
29 }
30 return *this;
31 }
32
lastIndexOf(char c) const33 int32_t CharString::lastIndexOf(char c) const {
34 for(int32_t i=len; i>0;) {
35 if(buffer[--i]==c) {
36 return i;
37 }
38 }
39 return -1;
40 }
41
truncate(int32_t newLength)42 CharString &CharString::truncate(int32_t newLength) {
43 if(newLength<0) {
44 newLength=0;
45 }
46 if(newLength<len) {
47 buffer[len=newLength]=0;
48 }
49 return *this;
50 }
51
append(char c,UErrorCode & errorCode)52 CharString &CharString::append(char c, UErrorCode &errorCode) {
53 if(ensureCapacity(len+2, 0, errorCode)) {
54 buffer[len++]=c;
55 buffer[len]=0;
56 }
57 return *this;
58 }
59
append(const char * s,int32_t sLength,UErrorCode & errorCode)60 CharString &CharString::append(const char *s, int32_t sLength, UErrorCode &errorCode) {
61 if(U_FAILURE(errorCode)) {
62 return *this;
63 }
64 if(sLength<-1 || (s==NULL && sLength!=0)) {
65 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
66 return *this;
67 }
68 if(sLength<0) {
69 sLength=uprv_strlen(s);
70 }
71 if(sLength>0) {
72 if(s==(buffer.getAlias()+len)) {
73 // The caller wrote into the getAppendBuffer().
74 if(sLength>=(buffer.getCapacity()-len)) {
75 // The caller wrote too much.
76 errorCode=U_INTERNAL_PROGRAM_ERROR;
77 } else {
78 buffer[len+=sLength]=0;
79 }
80 } else if(buffer.getAlias()<=s && s<(buffer.getAlias()+len) &&
81 sLength>=(buffer.getCapacity()-len)
82 ) {
83 // (Part of) this string is appended to itself which requires reallocation,
84 // so we have to make a copy of the substring and append that.
85 return append(CharString(s, sLength, errorCode), errorCode);
86 } else if(ensureCapacity(len+sLength+1, 0, errorCode)) {
87 uprv_memcpy(buffer.getAlias()+len, s, sLength);
88 buffer[len+=sLength]=0;
89 }
90 }
91 return *this;
92 }
93
getAppendBuffer(int32_t minCapacity,int32_t desiredCapacityHint,int32_t & resultCapacity,UErrorCode & errorCode)94 char *CharString::getAppendBuffer(int32_t minCapacity,
95 int32_t desiredCapacityHint,
96 int32_t &resultCapacity,
97 UErrorCode &errorCode) {
98 if(U_FAILURE(errorCode)) {
99 resultCapacity=0;
100 return NULL;
101 }
102 int32_t appendCapacity=buffer.getCapacity()-len-1; // -1 for NUL
103 if(appendCapacity>=minCapacity) {
104 resultCapacity=appendCapacity;
105 return buffer.getAlias()+len;
106 }
107 if(ensureCapacity(len+minCapacity+1, len+desiredCapacityHint+1, errorCode)) {
108 resultCapacity=buffer.getCapacity()-len-1;
109 return buffer.getAlias()+len;
110 }
111 resultCapacity=0;
112 return NULL;
113 }
114
appendInvariantChars(const UnicodeString & s,UErrorCode & errorCode)115 CharString &CharString::appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode) {
116 if(U_FAILURE(errorCode)) {
117 return *this;
118 }
119 if (!uprv_isInvariantUnicodeString(s)) {
120 errorCode = U_INVARIANT_CONVERSION_ERROR;
121 return *this;
122 }
123 if(ensureCapacity(len+s.length()+1, 0, errorCode)) {
124 len+=s.extract(0, 0x7fffffff, buffer.getAlias()+len, buffer.getCapacity()-len, US_INV);
125 }
126 return *this;
127 }
128
ensureCapacity(int32_t capacity,int32_t desiredCapacityHint,UErrorCode & errorCode)129 UBool CharString::ensureCapacity(int32_t capacity,
130 int32_t desiredCapacityHint,
131 UErrorCode &errorCode) {
132 if(U_FAILURE(errorCode)) {
133 return FALSE;
134 }
135 if(capacity>buffer.getCapacity()) {
136 if(desiredCapacityHint==0) {
137 desiredCapacityHint=capacity+buffer.getCapacity();
138 }
139 if( (desiredCapacityHint<=capacity || buffer.resize(desiredCapacityHint, len+1)==NULL) &&
140 buffer.resize(capacity, len+1)==NULL
141 ) {
142 errorCode=U_MEMORY_ALLOCATION_ERROR;
143 return FALSE;
144 }
145 }
146 return TRUE;
147 }
148
appendPathPart(StringPiece s,UErrorCode & errorCode)149 CharString &CharString::appendPathPart(StringPiece s, UErrorCode &errorCode) {
150 if(U_FAILURE(errorCode)) {
151 return *this;
152 }
153 if(s.length()==0) {
154 return *this;
155 }
156 char c;
157 if(len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
158 append(U_FILE_SEP_CHAR, errorCode);
159 }
160 append(s, errorCode);
161 return *this;
162 }
163
ensureEndsWithFileSeparator(UErrorCode & errorCode)164 CharString &CharString::ensureEndsWithFileSeparator(UErrorCode &errorCode) {
165 char c;
166 if(U_SUCCESS(errorCode) && len>0 &&
167 (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
168 append(U_FILE_SEP_CHAR, errorCode);
169 }
170 return *this;
171 }
172
173 U_NAMESPACE_END
174