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