1 // Copyright (C) 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: US-ASCII 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 "charstr.h" 19 #include "cmemory.h" 20 #include "cstring.h" 21 #include "uinvchar.h" 22 23 U_NAMESPACE_BEGIN 24 25 CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) { 26 if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) { 27 len=s.len; 28 uprv_memcpy(buffer.getAlias(), s.buffer.getAlias(), len+1); 29 } 30 return *this; 31 } 32 33 int32_t CharString::lastIndexOf(char c) const { 34 for(int32_t i=len; i>0;) { 35 if(buffer[--i]==c) { 36 return i; 37 } 38 } 39 return -1; 40 } 41 42 CharString &CharString::truncate(int32_t newLength) { 43 if(newLength<0) { 44 newLength=0; 45 } 46 if(newLength<len) { 47 buffer[len=newLength]=0; 48 } 49 return *this; 50 } 51 52 CharString &CharString::append(char c, UErrorCode &errorCode) { 53 if(ensureCapacity(len+2, 0, errorCode)) { 54 buffer[len++]=c; 55 buffer[len]=0; 56 } 57 return *this; 58 } 59 60 CharString &CharString::append(const char *s, int32_t sLength, UErrorCode &errorCode) { 61 if(U_FAILURE(errorCode)) { 62 return *this; 63 } 64 if(sLength<-1 || (s==NULL && sLength!=0)) { 65 errorCode=U_ILLEGAL_ARGUMENT_ERROR; 66 return *this; 67 } 68 if(sLength<0) { 69 sLength=uprv_strlen(s); 70 } 71 if(sLength>0) { 72 if(s==(buffer.getAlias()+len)) { 73 // The caller wrote into the getAppendBuffer(). 74 if(sLength>=(buffer.getCapacity()-len)) { 75 // The caller wrote too much. 76 errorCode=U_INTERNAL_PROGRAM_ERROR; 77 } else { 78 buffer[len+=sLength]=0; 79 } 80 } else if(buffer.getAlias()<=s && s<(buffer.getAlias()+len) && 81 sLength>=(buffer.getCapacity()-len) 82 ) { 83 // (Part of) this string is appended to itself which requires reallocation, 84 // so we have to make a copy of the substring and append that. 85 return append(CharString(s, sLength, errorCode), errorCode); 86 } else if(ensureCapacity(len+sLength+1, 0, errorCode)) { 87 uprv_memcpy(buffer.getAlias()+len, s, sLength); 88 buffer[len+=sLength]=0; 89 } 90 } 91 return *this; 92 } 93 94 char *CharString::getAppendBuffer(int32_t minCapacity, 95 int32_t desiredCapacityHint, 96 int32_t &resultCapacity, 97 UErrorCode &errorCode) { 98 if(U_FAILURE(errorCode)) { 99 resultCapacity=0; 100 return NULL; 101 } 102 int32_t appendCapacity=buffer.getCapacity()-len-1; // -1 for NUL 103 if(appendCapacity>=minCapacity) { 104 resultCapacity=appendCapacity; 105 return buffer.getAlias()+len; 106 } 107 if(ensureCapacity(len+minCapacity+1, len+desiredCapacityHint+1, errorCode)) { 108 resultCapacity=buffer.getCapacity()-len-1; 109 return buffer.getAlias()+len; 110 } 111 resultCapacity=0; 112 return NULL; 113 } 114 115 CharString &CharString::appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode) { 116 if(U_FAILURE(errorCode)) { 117 return *this; 118 } 119 if (!uprv_isInvariantUnicodeString(s)) { 120 errorCode = U_INVARIANT_CONVERSION_ERROR; 121 return *this; 122 } 123 if(ensureCapacity(len+s.length()+1, 0, errorCode)) { 124 len+=s.extract(0, 0x7fffffff, buffer.getAlias()+len, buffer.getCapacity()-len, US_INV); 125 } 126 return *this; 127 } 128 129 UBool CharString::ensureCapacity(int32_t capacity, 130 int32_t desiredCapacityHint, 131 UErrorCode &errorCode) { 132 if(U_FAILURE(errorCode)) { 133 return FALSE; 134 } 135 if(capacity>buffer.getCapacity()) { 136 if(desiredCapacityHint==0) { 137 desiredCapacityHint=capacity+buffer.getCapacity(); 138 } 139 if( (desiredCapacityHint<=capacity || buffer.resize(desiredCapacityHint, len+1)==NULL) && 140 buffer.resize(capacity, len+1)==NULL 141 ) { 142 errorCode=U_MEMORY_ALLOCATION_ERROR; 143 return FALSE; 144 } 145 } 146 return TRUE; 147 } 148 149 CharString &CharString::appendPathPart(StringPiece s, UErrorCode &errorCode) { 150 if(U_FAILURE(errorCode)) { 151 return *this; 152 } 153 if(s.length()==0) { 154 return *this; 155 } 156 char c; 157 if(len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) { 158 append(U_FILE_SEP_CHAR, errorCode); 159 } 160 append(s, errorCode); 161 return *this; 162 } 163 164 CharString &CharString::ensureEndsWithFileSeparator(UErrorCode &errorCode) { 165 char c; 166 if(U_SUCCESS(errorCode) && len>0 && 167 (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) { 168 append(U_FILE_SEP_CHAR, errorCode); 169 } 170 return *this; 171 } 172 173 U_NAMESPACE_END 174