Line data Source code
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 : }
31 0 : return *this;
32 : }
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 : }
39 : }
40 0 : return -1;
41 : }
42 :
43 0 : CharString &CharString::truncate(int32_t newLength) {
44 0 : if(newLength<0) {
45 0 : newLength=0;
46 : }
47 0 : if(newLength<len) {
48 0 : buffer[len=newLength]=0;
49 : }
50 0 : return *this;
51 : }
52 :
53 34 : CharString &CharString::append(char c, UErrorCode &errorCode) {
54 34 : if(ensureCapacity(len+2, 0, errorCode)) {
55 34 : buffer[len++]=c;
56 34 : buffer[len]=0;
57 : }
58 34 : return *this;
59 : }
60 :
61 104 : CharString &CharString::append(const char *s, int32_t sLength, UErrorCode &errorCode) {
62 104 : if(U_FAILURE(errorCode)) {
63 0 : return *this;
64 : }
65 104 : if(sLength<-1 || (s==NULL && sLength!=0)) {
66 0 : errorCode=U_ILLEGAL_ARGUMENT_ERROR;
67 0 : return *this;
68 : }
69 104 : if(sLength<0) {
70 0 : sLength=uprv_strlen(s);
71 : }
72 104 : if(sLength>0) {
73 103 : 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 : } else {
79 0 : buffer[len+=sLength]=0;
80 : }
81 103 : } else if(buffer.getAlias()<=s && s<(buffer.getAlias()+len) &&
82 0 : 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 0 : return append(CharString(s, sLength, errorCode), errorCode);
87 103 : } else if(ensureCapacity(len+sLength+1, 0, errorCode)) {
88 103 : uprv_memcpy(buffer.getAlias()+len, s, sLength);
89 103 : buffer[len+=sLength]=0;
90 : }
91 : }
92 104 : return *this;
93 : }
94 :
95 0 : char *CharString::getAppendBuffer(int32_t minCapacity,
96 : int32_t desiredCapacityHint,
97 : int32_t &resultCapacity,
98 : UErrorCode &errorCode) {
99 0 : if(U_FAILURE(errorCode)) {
100 0 : resultCapacity=0;
101 0 : return NULL;
102 : }
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 : }
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 : }
112 0 : resultCapacity=0;
113 0 : return NULL;
114 : }
115 :
116 0 : CharString &CharString::appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode) {
117 0 : if(U_FAILURE(errorCode)) {
118 0 : return *this;
119 : }
120 0 : if (!uprv_isInvariantUnicodeString(s)) {
121 0 : errorCode = U_INVARIANT_CONVERSION_ERROR;
122 0 : return *this;
123 : }
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 : }
127 0 : return *this;
128 : }
129 :
130 137 : UBool CharString::ensureCapacity(int32_t capacity,
131 : int32_t desiredCapacityHint,
132 : UErrorCode &errorCode) {
133 137 : if(U_FAILURE(errorCode)) {
134 0 : return FALSE;
135 : }
136 137 : if(capacity>buffer.getCapacity()) {
137 10 : if(desiredCapacityHint==0) {
138 10 : desiredCapacityHint=capacity+buffer.getCapacity();
139 : }
140 10 : if( (desiredCapacityHint<=capacity || buffer.resize(desiredCapacityHint, len+1)==NULL) &&
141 0 : buffer.resize(capacity, len+1)==NULL
142 : ) {
143 0 : errorCode=U_MEMORY_ALLOCATION_ERROR;
144 0 : return FALSE;
145 : }
146 : }
147 137 : return TRUE;
148 : }
149 :
150 0 : CharString &CharString::appendPathPart(StringPiece s, UErrorCode &errorCode) {
151 0 : if(U_FAILURE(errorCode)) {
152 0 : return *this;
153 : }
154 0 : if(s.length()==0) {
155 0 : return *this;
156 : }
157 : 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 : }
161 0 : append(s, errorCode);
162 0 : return *this;
163 : }
164 :
165 0 : CharString &CharString::ensureEndsWithFileSeparator(UErrorCode &errorCode) {
166 : 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 : }
171 0 : return *this;
172 : }
173 :
174 : U_NAMESPACE_END
|