Home | History | Annotate | Download | only in common
      1 /*
      2 *******************************************************************************
      3 *   Copyright (C) 2010-2011, 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 CharString &CharString::appendPathPart(const StringPiece &s, UErrorCode &errorCode) {
    131     if(U_FAILURE(errorCode)) {
    132         return *this;
    133     }
    134     if(s.length()==0) {
    135         return *this;
    136     }
    137     char c;
    138     if(len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
    139         append(U_FILE_SEP_CHAR, errorCode);
    140     }
    141     append(s, errorCode);
    142     return *this;
    143 }
    144 
    145 U_NAMESPACE_END
    146