/src/icu/source/common/charstr.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 0 | CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) { |
27 | 0 | if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) { |
28 | 0 | len=s.len; |
29 | 0 | uprv_memcpy(buffer.getAlias(), s.buffer.getAlias(), len+1); |
30 | 0 | } |
31 | 0 | return *this; |
32 | 0 | } |
33 | | |
34 | 0 | int32_t CharString::lastIndexOf(char c) const { |
35 | 0 | for(int32_t i=len; i>0;) { |
36 | 0 | if(buffer[--i]==c) { |
37 | 0 | return i; |
38 | 0 | } |
39 | 0 | } |
40 | 0 | return -1; |
41 | 0 | } |
42 | | |
43 | 0 | CharString &CharString::truncate(int32_t newLength) { |
44 | 0 | if(newLength<0) { |
45 | 0 | newLength=0; |
46 | 0 | } |
47 | 0 | if(newLength<len) { |
48 | 0 | buffer[len=newLength]=0; |
49 | 0 | } |
50 | 0 | return *this; |
51 | 0 | } |
52 | | |
53 | 2.38k | CharString &CharString::append(char c, UErrorCode &errorCode) { |
54 | 2.38k | if(ensureCapacity(len+2, 0, errorCode)) { |
55 | 2.38k | buffer[len++]=c; |
56 | 2.38k | buffer[len]=0; |
57 | 2.38k | } |
58 | 2.38k | return *this; |
59 | 2.38k | } |
60 | | |
61 | 10.7k | CharString &CharString::append(const char *s, int32_t sLength, UErrorCode &errorCode) { |
62 | 10.7k | if(U_FAILURE(errorCode)) { |
63 | 0 | return *this; |
64 | 0 | } |
65 | 10.7k | if(sLength<-1 || (s==NULL && sLength!=0)) { |
66 | 0 | errorCode=U_ILLEGAL_ARGUMENT_ERROR; |
67 | 0 | return *this; |
68 | 0 | } |
69 | 10.7k | if(sLength<0) { |
70 | 0 | sLength=uprv_strlen(s); |
71 | 0 | } |
72 | 10.7k | if(sLength>0) { |
73 | 10.7k | if(s==(buffer.getAlias()+len)) { |
74 | | // The caller wrote into the getAppendBuffer(). |
75 | 0 | if(sLength>=(buffer.getCapacity()-len)) { |
76 | | // The caller wrote too much. |
77 | 0 | errorCode=U_INTERNAL_PROGRAM_ERROR; |
78 | 0 | } else { |
79 | 0 | buffer[len+=sLength]=0; |
80 | 0 | } |
81 | 10.7k | } else if(buffer.getAlias()<=s && s<(buffer.getAlias()+len) && |
82 | 10.7k | sLength>=(buffer.getCapacity()-len) |
83 | 10.7k | ) { |
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 | 0 | return append(CharString(s, sLength, errorCode), errorCode); |
87 | 10.7k | } else if(ensureCapacity(len+sLength+1, 0, errorCode)) { |
88 | 10.7k | uprv_memcpy(buffer.getAlias()+len, s, sLength); |
89 | 10.7k | buffer[len+=sLength]=0; |
90 | 10.7k | } |
91 | 10.7k | } |
92 | 10.7k | return *this; |
93 | 10.7k | } |
94 | | |
95 | | char *CharString::getAppendBuffer(int32_t minCapacity, |
96 | | int32_t desiredCapacityHint, |
97 | | int32_t &resultCapacity, |
98 | 0 | UErrorCode &errorCode) { |
99 | 0 | if(U_FAILURE(errorCode)) { |
100 | 0 | resultCapacity=0; |
101 | 0 | return NULL; |
102 | 0 | } |
103 | 0 | int32_t appendCapacity=buffer.getCapacity()-len-1; // -1 for NUL |
104 | 0 | if(appendCapacity>=minCapacity) { |
105 | 0 | resultCapacity=appendCapacity; |
106 | 0 | return buffer.getAlias()+len; |
107 | 0 | } |
108 | 0 | if(ensureCapacity(len+minCapacity+1, len+desiredCapacityHint+1, errorCode)) { |
109 | 0 | resultCapacity=buffer.getCapacity()-len-1; |
110 | 0 | return buffer.getAlias()+len; |
111 | 0 | } |
112 | 0 | resultCapacity=0; |
113 | 0 | return NULL; |
114 | 0 | } |
115 | | |
116 | 0 | CharString &CharString::appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode) { |
117 | 0 | if(U_FAILURE(errorCode)) { |
118 | 0 | return *this; |
119 | 0 | } |
120 | 0 | if (!uprv_isInvariantUnicodeString(s)) { |
121 | 0 | errorCode = U_INVARIANT_CONVERSION_ERROR; |
122 | 0 | return *this; |
123 | 0 | } |
124 | 0 | if(ensureCapacity(len+s.length()+1, 0, errorCode)) { |
125 | 0 | len+=s.extract(0, 0x7fffffff, buffer.getAlias()+len, buffer.getCapacity()-len, US_INV); |
126 | 0 | } |
127 | 0 | return *this; |
128 | 0 | } |
129 | | |
130 | | UBool CharString::ensureCapacity(int32_t capacity, |
131 | | int32_t desiredCapacityHint, |
132 | 13.1k | UErrorCode &errorCode) { |
133 | 13.1k | if(U_FAILURE(errorCode)) { |
134 | 0 | return FALSE; |
135 | 0 | } |
136 | 13.1k | if(capacity>buffer.getCapacity()) { |
137 | 0 | if(desiredCapacityHint==0) { |
138 | 0 | desiredCapacityHint=capacity+buffer.getCapacity(); |
139 | 0 | } |
140 | 0 | if( (desiredCapacityHint<=capacity || buffer.resize(desiredCapacityHint, len+1)==NULL) && |
141 | 0 | buffer.resize(capacity, len+1)==NULL |
142 | 0 | ) { |
143 | 0 | errorCode=U_MEMORY_ALLOCATION_ERROR; |
144 | 0 | return FALSE; |
145 | 0 | } |
146 | 0 | } |
147 | 13.1k | return TRUE; |
148 | 13.1k | } |
149 | | |
150 | 0 | CharString &CharString::appendPathPart(StringPiece s, UErrorCode &errorCode) { |
151 | 0 | if(U_FAILURE(errorCode)) { |
152 | 0 | return *this; |
153 | 0 | } |
154 | 0 | if(s.length()==0) { |
155 | 0 | return *this; |
156 | 0 | } |
157 | 0 | char c; |
158 | 0 | if(len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) { |
159 | 0 | append(U_FILE_SEP_CHAR, errorCode); |
160 | 0 | } |
161 | 0 | append(s, errorCode); |
162 | 0 | return *this; |
163 | 0 | } |
164 | | |
165 | 0 | CharString &CharString::ensureEndsWithFileSeparator(UErrorCode &errorCode) { |
166 | 0 | char c; |
167 | 0 | if(U_SUCCESS(errorCode) && len>0 && |
168 | 0 | (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) { |
169 | 0 | append(U_FILE_SEP_CHAR, errorCode); |
170 | 0 | } |
171 | 0 | return *this; |
172 | 0 | } |
173 | | |
174 | | U_NAMESPACE_END |