• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
copyFrom(const CharString & s,UErrorCode & errorCode)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  
truncate(int32_t newLength)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  
append(char c,UErrorCode & errorCode)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  
append(const char * s,int32_t sLength,UErrorCode & errorCode)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  
getAppendBuffer(int32_t minCapacity,int32_t desiredCapacityHint,int32_t & resultCapacity,UErrorCode & errorCode)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  
appendInvariantChars(const UnicodeString & s,UErrorCode & errorCode)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  
ensureCapacity(int32_t capacity,int32_t desiredCapacityHint,UErrorCode & errorCode)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