• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CharString(CharString && src)26 CharString::CharString(CharString&& src) U_NOEXCEPT
27         : buffer(std::move(src.buffer)), len(src.len) {
28     src.len = 0;  // not strictly necessary because we make no guarantees on the source string
29 }
30 
operator =(CharString && src)31 CharString& CharString::operator=(CharString&& src) U_NOEXCEPT {
32     buffer = std::move(src.buffer);
33     len = src.len;
34     src.len = 0;  // not strictly necessary because we make no guarantees on the source string
35     return *this;
36 }
37 
cloneData(UErrorCode & errorCode) const38 char *CharString::cloneData(UErrorCode &errorCode) const {
39     if (U_FAILURE(errorCode)) { return nullptr; }
40     char *p = static_cast<char *>(uprv_malloc(len + 1));
41     if (p == nullptr) {
42         errorCode = U_MEMORY_ALLOCATION_ERROR;
43         return nullptr;
44     }
45     uprv_memcpy(p, buffer.getAlias(), len + 1);
46     return p;
47 }
48 
copyFrom(const CharString & s,UErrorCode & errorCode)49 CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) {
50     if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) {
51         len=s.len;
52         uprv_memcpy(buffer.getAlias(), s.buffer.getAlias(), len+1);
53     }
54     return *this;
55 }
56 
lastIndexOf(char c) const57 int32_t CharString::lastIndexOf(char c) const {
58     for(int32_t i=len; i>0;) {
59         if(buffer[--i]==c) {
60             return i;
61         }
62     }
63     return -1;
64 }
65 
contains(StringPiece s) const66 bool CharString::contains(StringPiece s) const {
67     if (s.empty()) { return false; }
68     const char *p = buffer.getAlias();
69     int32_t lastStart = len - s.length();
70     for (int32_t i = 0; i <= lastStart; ++i) {
71         if (uprv_memcmp(p + i, s.data(), s.length()) == 0) {
72             return true;
73         }
74     }
75     return false;
76 }
77 
truncate(int32_t newLength)78 CharString &CharString::truncate(int32_t newLength) {
79     if(newLength<0) {
80         newLength=0;
81     }
82     if(newLength<len) {
83         buffer[len=newLength]=0;
84     }
85     return *this;
86 }
87 
append(char c,UErrorCode & errorCode)88 CharString &CharString::append(char c, UErrorCode &errorCode) {
89     if(ensureCapacity(len+2, 0, errorCode)) {
90         buffer[len++]=c;
91         buffer[len]=0;
92     }
93     return *this;
94 }
95 
append(const char * s,int32_t sLength,UErrorCode & errorCode)96 CharString &CharString::append(const char *s, int32_t sLength, UErrorCode &errorCode) {
97     if(U_FAILURE(errorCode)) {
98         return *this;
99     }
100     if(sLength<-1 || (s==NULL && sLength!=0)) {
101         errorCode=U_ILLEGAL_ARGUMENT_ERROR;
102         return *this;
103     }
104     if(sLength<0) {
105         sLength= static_cast<int32_t>(uprv_strlen(s));
106     }
107     if(sLength>0) {
108         if(s==(buffer.getAlias()+len)) {
109             // The caller wrote into the getAppendBuffer().
110             if(sLength>=(buffer.getCapacity()-len)) {
111                 // The caller wrote too much.
112                 errorCode=U_INTERNAL_PROGRAM_ERROR;
113             } else {
114                 buffer[len+=sLength]=0;
115             }
116         } else if(buffer.getAlias()<=s && s<(buffer.getAlias()+len) &&
117                   sLength>=(buffer.getCapacity()-len)
118         ) {
119             // (Part of) this string is appended to itself which requires reallocation,
120             // so we have to make a copy of the substring and append that.
121             return append(CharString(s, sLength, errorCode), errorCode);
122         } else if(ensureCapacity(len+sLength+1, 0, errorCode)) {
123             uprv_memcpy(buffer.getAlias()+len, s, sLength);
124             buffer[len+=sLength]=0;
125         }
126     }
127     return *this;
128 }
129 
getAppendBuffer(int32_t minCapacity,int32_t desiredCapacityHint,int32_t & resultCapacity,UErrorCode & errorCode)130 char *CharString::getAppendBuffer(int32_t minCapacity,
131                                   int32_t desiredCapacityHint,
132                                   int32_t &resultCapacity,
133                                   UErrorCode &errorCode) {
134     if(U_FAILURE(errorCode)) {
135         resultCapacity=0;
136         return NULL;
137     }
138     int32_t appendCapacity=buffer.getCapacity()-len-1;  // -1 for NUL
139     if(appendCapacity>=minCapacity) {
140         resultCapacity=appendCapacity;
141         return buffer.getAlias()+len;
142     }
143     if(ensureCapacity(len+minCapacity+1, len+desiredCapacityHint+1, errorCode)) {
144         resultCapacity=buffer.getCapacity()-len-1;
145         return buffer.getAlias()+len;
146     }
147     resultCapacity=0;
148     return NULL;
149 }
150 
appendInvariantChars(const UnicodeString & s,UErrorCode & errorCode)151 CharString &CharString::appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode) {
152     return appendInvariantChars(s.getBuffer(), s.length(), errorCode);
153 }
154 
appendInvariantChars(const UChar * uchars,int32_t ucharsLen,UErrorCode & errorCode)155 CharString &CharString::appendInvariantChars(const UChar* uchars, int32_t ucharsLen, UErrorCode &errorCode) {
156     if(U_FAILURE(errorCode)) {
157         return *this;
158     }
159     if (!uprv_isInvariantUString(uchars, ucharsLen)) {
160         errorCode = U_INVARIANT_CONVERSION_ERROR;
161         return *this;
162     }
163     if(ensureCapacity(len+ucharsLen+1, 0, errorCode)) {
164         u_UCharsToChars(uchars, buffer.getAlias()+len, ucharsLen);
165         len += ucharsLen;
166         buffer[len] = 0;
167     }
168     return *this;
169 }
170 
ensureCapacity(int32_t capacity,int32_t desiredCapacityHint,UErrorCode & errorCode)171 UBool CharString::ensureCapacity(int32_t capacity,
172                                  int32_t desiredCapacityHint,
173                                  UErrorCode &errorCode) {
174     if(U_FAILURE(errorCode)) {
175         return FALSE;
176     }
177     if(capacity>buffer.getCapacity()) {
178         if(desiredCapacityHint==0) {
179             desiredCapacityHint=capacity+buffer.getCapacity();
180         }
181         if( (desiredCapacityHint<=capacity || buffer.resize(desiredCapacityHint, len+1)==NULL) &&
182             buffer.resize(capacity, len+1)==NULL
183         ) {
184             errorCode=U_MEMORY_ALLOCATION_ERROR;
185             return FALSE;
186         }
187     }
188     return TRUE;
189 }
190 
appendPathPart(StringPiece s,UErrorCode & errorCode)191 CharString &CharString::appendPathPart(StringPiece s, UErrorCode &errorCode) {
192     if(U_FAILURE(errorCode)) {
193         return *this;
194     }
195     if(s.length()==0) {
196         return *this;
197     }
198     char c;
199     if(len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
200         append(U_FILE_SEP_CHAR, errorCode);
201     }
202     append(s, errorCode);
203     return *this;
204 }
205 
ensureEndsWithFileSeparator(UErrorCode & errorCode)206 CharString &CharString::ensureEndsWithFileSeparator(UErrorCode &errorCode) {
207     char c;
208     if(U_SUCCESS(errorCode) && len>0 &&
209             (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
210         append(U_FILE_SEP_CHAR, errorCode);
211     }
212     return *this;
213 }
214 
215 U_NAMESPACE_END
216