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