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