1 /*
2 *******************************************************************************
3 * Copyright (C) 2010, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 *******************************************************************************
6 * file name: charstr.cpp
7 * encoding: US-ASCII
8 * tab size: 8 (not used)
9 * indentation:4
10 *
11 * created on: 2010may19
12 * created by: Markus W. Scherer
13 */
14
15 #include "unicode/utypes.h"
16 #include "charstr.h"
17 #include "cmemory.h"
18 #include "cstring.h"
19
20 U_NAMESPACE_BEGIN
21
copyFrom(const CharString & s,UErrorCode & errorCode)22 CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) {
23 if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) {
24 len=s.len;
25 uprv_memcpy(buffer.getAlias(), s.buffer.getAlias(), len+1);
26 }
27 return *this;
28 }
29
truncate(int32_t newLength)30 CharString &CharString::truncate(int32_t newLength) {
31 if(newLength<0) {
32 newLength=0;
33 }
34 if(newLength<len) {
35 buffer[len=newLength]=0;
36 }
37 return *this;
38 }
39
append(char c,UErrorCode & errorCode)40 CharString &CharString::append(char c, UErrorCode &errorCode) {
41 if(ensureCapacity(len+2, 0, errorCode)) {
42 buffer[len++]=c;
43 buffer[len]=0;
44 }
45 return *this;
46 }
47
append(const char * s,int32_t sLength,UErrorCode & errorCode)48 CharString &CharString::append(const char *s, int32_t sLength, UErrorCode &errorCode) {
49 if(U_FAILURE(errorCode)) {
50 return *this;
51 }
52 if(sLength<-1 || (s==NULL && sLength!=0)) {
53 errorCode=U_ILLEGAL_ARGUMENT_ERROR;
54 return *this;
55 }
56 if(sLength<0) {
57 sLength=uprv_strlen(s);
58 }
59 if(sLength>0) {
60 if(s==(buffer.getAlias()+len)) {
61 // The caller wrote into the getAppendBuffer().
62 if(sLength>=(buffer.getCapacity()-len)) {
63 // The caller wrote too much.
64 errorCode=U_INTERNAL_PROGRAM_ERROR;
65 } else {
66 buffer[len+=sLength]=0;
67 }
68 } else if(buffer.getAlias()<=s && s<(buffer.getAlias()+len) &&
69 sLength>=(buffer.getCapacity()-len)
70 ) {
71 // (Part of) this string is appended to itself which requires reallocation,
72 // so we have to make a copy of the substring and append that.
73 return append(CharString(s, sLength, errorCode), errorCode);
74 } else if(ensureCapacity(len+sLength+1, 0, errorCode)) {
75 uprv_memcpy(buffer.getAlias()+len, s, sLength);
76 buffer[len+=sLength]=0;
77 }
78 }
79 return *this;
80 }
81
getAppendBuffer(int32_t minCapacity,int32_t desiredCapacityHint,int32_t & resultCapacity,UErrorCode & errorCode)82 char *CharString::getAppendBuffer(int32_t minCapacity,
83 int32_t desiredCapacityHint,
84 int32_t &resultCapacity,
85 UErrorCode &errorCode) {
86 if(U_FAILURE(errorCode)) {
87 resultCapacity=0;
88 return NULL;
89 }
90 int32_t appendCapacity=buffer.getCapacity()-len-1; // -1 for NUL
91 if(appendCapacity>=minCapacity) {
92 resultCapacity=appendCapacity;
93 return buffer.getAlias()+len;
94 }
95 if(ensureCapacity(len+minCapacity+1, len+desiredCapacityHint+1, errorCode)) {
96 resultCapacity=buffer.getCapacity()-len-1;
97 return buffer.getAlias()+len;
98 }
99 resultCapacity=0;
100 return NULL;
101 }
102
appendInvariantChars(const UnicodeString & s,UErrorCode & errorCode)103 CharString &CharString::appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode) {
104 if(ensureCapacity(len+s.length()+1, 0, errorCode)) {
105 len+=s.extract(0, 0x7fffffff, buffer.getAlias()+len, buffer.getCapacity()-len, US_INV);
106 }
107 return *this;
108 }
109
ensureCapacity(int32_t capacity,int32_t desiredCapacityHint,UErrorCode & errorCode)110 UBool CharString::ensureCapacity(int32_t capacity,
111 int32_t desiredCapacityHint,
112 UErrorCode &errorCode) {
113 if(U_FAILURE(errorCode)) {
114 return FALSE;
115 }
116 if(capacity>buffer.getCapacity()) {
117 if(desiredCapacityHint==0) {
118 desiredCapacityHint=capacity+buffer.getCapacity();
119 }
120 if( (desiredCapacityHint<=capacity || buffer.resize(desiredCapacityHint, len+1)==NULL) &&
121 buffer.resize(capacity, len+1)==NULL
122 ) {
123 errorCode=U_MEMORY_ALLOCATION_ERROR;
124 return FALSE;
125 }
126 }
127 return TRUE;
128 }
129
130 U_NAMESPACE_END
131