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