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