1 /*
2 *******************************************************************************
3 *
4 *   Copyright (C) 1998-2012, International Business Machines
5 *   Corporation and others.  All Rights Reserved.
6 *
7 *******************************************************************************
8 *
9 * File ustr.c
10 *
11 * Modification History:
12 *
13 *   Date        Name        Description
14 *   05/28/99    stephen     Creation.
15 *******************************************************************************
16 */
17 
18 #include "ustr.h"
19 #include "cmemory.h"
20 #include "cstring.h"
21 #include "unicode/ustring.h"
22 #include "unicode/putil.h"
23 #include "unicode/utf16.h"
24 
25 /* Protos */
26 static void ustr_resize(struct UString *s, int32_t len, UErrorCode *status);
27 
28 /* Macros */
29 #define ALLOCATION(minSize) (minSize < 0x80 ? 0x80 : (2 * minSize + 0x80) & ~(0x80 - 1))
30 
31 U_CFUNC void
ustr_init(struct UString * s)32 ustr_init(struct UString *s)
33 {
34     s->fChars = 0;
35     s->fLength = s->fCapacity = 0;
36 }
37 
38 U_CFUNC void
ustr_initChars(struct UString * s,const char * source,int32_t length,UErrorCode * status)39 ustr_initChars(struct UString *s, const char* source, int32_t length, UErrorCode *status)
40 {
41     int i = 0;
42     if (U_FAILURE(*status)) return;
43     s->fChars = 0;
44     s->fLength = s->fCapacity = 0;
45     if (length == -1) {
46         length = (int32_t)uprv_strlen(source);
47     }
48     if(s->fCapacity < length) {
49       ustr_resize(s, ALLOCATION(length), status);
50       if(U_FAILURE(*status)) return;
51     }
52     for (; i < length; i++)
53     {
54       UChar charToAppend;
55       u_charsToUChars(source+i, &charToAppend, 1);
56       ustr_ucat(s, charToAppend, status);
57       /*
58 #if U_CHARSET_FAMILY==U_ASCII_FAMILY
59         ustr_ucat(s, (UChar)(uint8_t)(source[i]), status);
60 #elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY
61         ustr_ucat(s, (UChar)asciiFromEbcdic[(uint8_t)(*cs++)], status);
62 #else
63 #   error U_CHARSET_FAMILY is not valid
64 #endif
65       */
66     }
67 }
68 
69 U_CFUNC void
ustr_deinit(struct UString * s)70 ustr_deinit(struct UString *s)
71 {
72     if (s) {
73         uprv_free(s->fChars);
74         s->fChars = 0;
75         s->fLength = s->fCapacity = 0;
76     }
77 }
78 
79 U_CFUNC void
ustr_cpy(struct UString * dst,const struct UString * src,UErrorCode * status)80 ustr_cpy(struct UString *dst,
81      const struct UString *src,
82      UErrorCode *status)
83 {
84     if(U_FAILURE(*status) || dst == src)
85         return;
86 
87     if(dst->fCapacity < src->fLength) {
88         ustr_resize(dst, ALLOCATION(src->fLength), status);
89         if(U_FAILURE(*status))
90             return;
91     }
92     if(src->fChars == NULL || dst->fChars == NULL){
93         return;
94     }
95     uprv_memcpy(dst->fChars, src->fChars, sizeof(UChar) * src->fLength);
96     dst->fLength = src->fLength;
97     dst->fChars[dst->fLength] = 0x0000;
98 }
99 
100 U_CFUNC void
ustr_setlen(struct UString * s,int32_t len,UErrorCode * status)101 ustr_setlen(struct UString *s,
102         int32_t len,
103         UErrorCode *status)
104 {
105     if(U_FAILURE(*status))
106         return;
107 
108     if(s->fCapacity < (len + 1)) {
109         ustr_resize(s, ALLOCATION(len), status);
110         if(U_FAILURE(*status))
111             return;
112     }
113 
114     s->fLength = len;
115     s->fChars[len] = 0x0000;
116 }
117 
118 U_CFUNC void
ustr_cat(struct UString * dst,const struct UString * src,UErrorCode * status)119 ustr_cat(struct UString *dst,
120      const struct UString *src,
121      UErrorCode *status)
122 {
123     ustr_ncat(dst, src, src->fLength, status);
124 }
125 
126 U_CFUNC void
ustr_ncat(struct UString * dst,const struct UString * src,int32_t n,UErrorCode * status)127 ustr_ncat(struct UString *dst,
128       const struct UString *src,
129       int32_t n,
130       UErrorCode *status)
131 {
132     if(U_FAILURE(*status) || dst == src)
133         return;
134 
135     if(dst->fCapacity < (dst->fLength + n)) {
136         ustr_resize(dst, ALLOCATION(dst->fLength + n), status);
137         if(U_FAILURE(*status))
138             return;
139     }
140 
141     uprv_memcpy(dst->fChars + dst->fLength, src->fChars,
142                 sizeof(UChar) * n);
143     dst->fLength += src->fLength;
144     dst->fChars[dst->fLength] = 0x0000;
145 }
146 
147 U_CFUNC void
ustr_ucat(struct UString * dst,UChar c,UErrorCode * status)148 ustr_ucat(struct UString *dst,
149       UChar c,
150       UErrorCode *status)
151 {
152     if(U_FAILURE(*status))
153         return;
154 
155     if(dst->fCapacity < (dst->fLength + 1)) {
156         ustr_resize(dst, ALLOCATION(dst->fLength + 1), status);
157         if(U_FAILURE(*status))
158             return;
159     }
160 
161     uprv_memcpy(dst->fChars + dst->fLength, &c,
162         sizeof(UChar) * 1);
163     dst->fLength += 1;
164     dst->fChars[dst->fLength] = 0x0000;
165 }
166 U_CFUNC void
ustr_u32cat(struct UString * dst,UChar32 c,UErrorCode * status)167 ustr_u32cat(struct UString *dst, UChar32 c, UErrorCode *status){
168     if(c > 0x10FFFF){
169         *status = U_ILLEGAL_CHAR_FOUND;
170         return;
171     }
172     if(c >0xFFFF){
173         ustr_ucat(dst, U16_LEAD(c), status);
174         ustr_ucat(dst, U16_TRAIL(c), status);
175     }else{
176         ustr_ucat(dst, (UChar) c, status);
177     }
178 }
179 U_CFUNC void
ustr_uscat(struct UString * dst,const UChar * src,int len,UErrorCode * status)180 ustr_uscat(struct UString *dst,
181       const UChar* src,int len,
182       UErrorCode *status)
183 {
184     if(U_FAILURE(*status))
185         return;
186 
187     if(dst->fCapacity < (dst->fLength + len)) {
188         ustr_resize(dst, ALLOCATION(dst->fLength + len), status);
189         if(U_FAILURE(*status))
190             return;
191     }
192 
193     uprv_memcpy(dst->fChars + dst->fLength, src,
194         sizeof(UChar) * len);
195     dst->fLength += len;
196     dst->fChars[dst->fLength] = 0x0000;
197 }
198 
199 /* Destroys data in the string */
200 static void
ustr_resize(struct UString * s,int32_t len,UErrorCode * status)201 ustr_resize(struct UString *s,
202         int32_t len,
203         UErrorCode *status)
204 {
205     if(U_FAILURE(*status))
206         return;
207 
208     /* +1 for trailing 0x0000 */
209     s->fChars = (UChar*) uprv_realloc(s->fChars, sizeof(UChar) * (len + 1));
210     if(s->fChars == 0) {
211         *status = U_MEMORY_ALLOCATION_ERROR;
212         s->fLength = s->fCapacity = 0;
213         return;
214     }
215 
216     s->fCapacity = len;
217 }
218