• 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 
copyFrom(const CharString & s,UErrorCode & errorCode)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 
lastIndexOf(char c) const34 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 
truncate(int32_t newLength)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 
append(char c,UErrorCode & errorCode)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 
append(const char * s,int32_t sLength,UErrorCode & errorCode)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 
getAppendBuffer(int32_t minCapacity,int32_t desiredCapacityHint,int32_t & resultCapacity,UErrorCode & errorCode)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 
appendInvariantChars(const UnicodeString & s,UErrorCode & errorCode)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 
ensureCapacity(int32_t capacity,int32_t desiredCapacityHint,UErrorCode & errorCode)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 
appendPathPart(StringPiece s,UErrorCode & errorCode)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 
ensureEndsWithFileSeparator(UErrorCode & errorCode)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
175