/src/mozilla-central/intl/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 | | CharString::CharString(CharString&& src) U_NOEXCEPT |
27 | 0 | : buffer(std::move(src.buffer)), len(src.len) { |
28 | 0 | src.len = 0; // not strictly necessary because we make no guarantees on the source string |
29 | 0 | } |
30 | | |
31 | 0 | CharString& CharString::operator=(CharString&& src) U_NOEXCEPT { |
32 | 0 | buffer = std::move(src.buffer); |
33 | 0 | len = src.len; |
34 | 0 | src.len = 0; // not strictly necessary because we make no guarantees on the source string |
35 | 0 | return *this; |
36 | 0 | } |
37 | | |
38 | 0 | CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) { |
39 | 0 | if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) { |
40 | 0 | len=s.len; |
41 | 0 | uprv_memcpy(buffer.getAlias(), s.buffer.getAlias(), len+1); |
42 | 0 | } |
43 | 0 | return *this; |
44 | 0 | } |
45 | | |
46 | 0 | int32_t CharString::lastIndexOf(char c) const { |
47 | 0 | for(int32_t i=len; i>0;) { |
48 | 0 | if(buffer[--i]==c) { |
49 | 0 | return i; |
50 | 0 | } |
51 | 0 | } |
52 | 0 | return -1; |
53 | 0 | } |
54 | | |
55 | 0 | CharString &CharString::truncate(int32_t newLength) { |
56 | 0 | if(newLength<0) { |
57 | 0 | newLength=0; |
58 | 0 | } |
59 | 0 | if(newLength<len) { |
60 | 0 | buffer[len=newLength]=0; |
61 | 0 | } |
62 | 0 | return *this; |
63 | 0 | } |
64 | | |
65 | 18 | CharString &CharString::append(char c, UErrorCode &errorCode) { |
66 | 18 | if(ensureCapacity(len+2, 0, errorCode)) { |
67 | 18 | buffer[len++]=c; |
68 | 18 | buffer[len]=0; |
69 | 18 | } |
70 | 18 | return *this; |
71 | 18 | } |
72 | | |
73 | 81 | CharString &CharString::append(const char *s, int32_t sLength, UErrorCode &errorCode) { |
74 | 81 | if(U_FAILURE(errorCode)) { |
75 | 0 | return *this; |
76 | 0 | } |
77 | 81 | if(sLength<-1 || (s==NULL && sLength!=0)) { |
78 | 0 | errorCode=U_ILLEGAL_ARGUMENT_ERROR; |
79 | 0 | return *this; |
80 | 0 | } |
81 | 81 | if(sLength<0) { |
82 | 0 | sLength=uprv_strlen(s); |
83 | 0 | } |
84 | 81 | if(sLength>0) { |
85 | 81 | if(s==(buffer.getAlias()+len)) { |
86 | 0 | // The caller wrote into the getAppendBuffer(). |
87 | 0 | if(sLength>=(buffer.getCapacity()-len)) { |
88 | 0 | // The caller wrote too much. |
89 | 0 | errorCode=U_INTERNAL_PROGRAM_ERROR; |
90 | 0 | } else { |
91 | 0 | buffer[len+=sLength]=0; |
92 | 0 | } |
93 | 81 | } else if(buffer.getAlias()<=s && s<(buffer.getAlias()+len) && |
94 | 81 | sLength>=(buffer.getCapacity()-len) |
95 | 0 | ) { |
96 | 0 | // (Part of) this string is appended to itself which requires reallocation, |
97 | 0 | // so we have to make a copy of the substring and append that. |
98 | 0 | return append(CharString(s, sLength, errorCode), errorCode); |
99 | 81 | } else if(ensureCapacity(len+sLength+1, 0, errorCode)) { |
100 | 81 | uprv_memcpy(buffer.getAlias()+len, s, sLength); |
101 | 81 | buffer[len+=sLength]=0; |
102 | 81 | } |
103 | 81 | } |
104 | 81 | return *this; |
105 | 81 | } |
106 | | |
107 | | char *CharString::getAppendBuffer(int32_t minCapacity, |
108 | | int32_t desiredCapacityHint, |
109 | | int32_t &resultCapacity, |
110 | 0 | UErrorCode &errorCode) { |
111 | 0 | if(U_FAILURE(errorCode)) { |
112 | 0 | resultCapacity=0; |
113 | 0 | return NULL; |
114 | 0 | } |
115 | 0 | int32_t appendCapacity=buffer.getCapacity()-len-1; // -1 for NUL |
116 | 0 | if(appendCapacity>=minCapacity) { |
117 | 0 | resultCapacity=appendCapacity; |
118 | 0 | return buffer.getAlias()+len; |
119 | 0 | } |
120 | 0 | if(ensureCapacity(len+minCapacity+1, len+desiredCapacityHint+1, errorCode)) { |
121 | 0 | resultCapacity=buffer.getCapacity()-len-1; |
122 | 0 | return buffer.getAlias()+len; |
123 | 0 | } |
124 | 0 | resultCapacity=0; |
125 | 0 | return NULL; |
126 | 0 | } |
127 | | |
128 | 0 | CharString &CharString::appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode) { |
129 | 0 | if(U_FAILURE(errorCode)) { |
130 | 0 | return *this; |
131 | 0 | } |
132 | 0 | if (!uprv_isInvariantUnicodeString(s)) { |
133 | 0 | errorCode = U_INVARIANT_CONVERSION_ERROR; |
134 | 0 | return *this; |
135 | 0 | } |
136 | 0 | if(ensureCapacity(len+s.length()+1, 0, errorCode)) { |
137 | 0 | len+=s.extract(0, 0x7fffffff, buffer.getAlias()+len, buffer.getCapacity()-len, US_INV); |
138 | 0 | } |
139 | 0 | return *this; |
140 | 0 | } |
141 | | |
142 | | UBool CharString::ensureCapacity(int32_t capacity, |
143 | | int32_t desiredCapacityHint, |
144 | 99 | UErrorCode &errorCode) { |
145 | 99 | if(U_FAILURE(errorCode)) { |
146 | 0 | return FALSE; |
147 | 0 | } |
148 | 99 | if(capacity>buffer.getCapacity()) { |
149 | 0 | if(desiredCapacityHint==0) { |
150 | 0 | desiredCapacityHint=capacity+buffer.getCapacity(); |
151 | 0 | } |
152 | 0 | if( (desiredCapacityHint<=capacity || buffer.resize(desiredCapacityHint, len+1)==NULL) && |
153 | 0 | buffer.resize(capacity, len+1)==NULL |
154 | 0 | ) { |
155 | 0 | errorCode=U_MEMORY_ALLOCATION_ERROR; |
156 | 0 | return FALSE; |
157 | 0 | } |
158 | 99 | } |
159 | 99 | return TRUE; |
160 | 99 | } |
161 | | |
162 | 0 | CharString &CharString::appendPathPart(StringPiece s, UErrorCode &errorCode) { |
163 | 0 | if(U_FAILURE(errorCode)) { |
164 | 0 | return *this; |
165 | 0 | } |
166 | 0 | if(s.length()==0) { |
167 | 0 | return *this; |
168 | 0 | } |
169 | 0 | char c; |
170 | 0 | if(len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) { |
171 | 0 | append(U_FILE_SEP_CHAR, errorCode); |
172 | 0 | } |
173 | 0 | append(s, errorCode); |
174 | 0 | return *this; |
175 | 0 | } |
176 | | |
177 | 0 | CharString &CharString::ensureEndsWithFileSeparator(UErrorCode &errorCode) { |
178 | 0 | char c; |
179 | 0 | if(U_SUCCESS(errorCode) && len>0 && |
180 | 0 | (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) { |
181 | 0 | append(U_FILE_SEP_CHAR, errorCode); |
182 | 0 | } |
183 | 0 | return *this; |
184 | 0 | } |
185 | | |
186 | | U_NAMESPACE_END |