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