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 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 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 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 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 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 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 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