1 /* |
1 /* |
2 * File: sstring.c |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 * Author: olaf |
3 * |
4 * |
4 * Copyright 2013 Olaf Wintermann. All rights reserved. |
5 * Created on 17. Juni 2010, 13:27 |
5 * |
|
6 * Redistribution and use in source and binary forms, with or without |
|
7 * modification, are permitted provided that the following conditions are met: |
|
8 * |
|
9 * 1. Redistributions of source code must retain the above copyright |
|
10 * notice, this list of conditions and the following disclaimer. |
|
11 * |
|
12 * 2. Redistributions in binary form must reproduce the above copyright |
|
13 * notice, this list of conditions and the following disclaimer in the |
|
14 * documentation and/or other materials provided with the distribution. |
|
15 * |
|
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
26 * POSSIBILITY OF SUCH DAMAGE. |
6 */ |
27 */ |
7 |
28 |
8 #include <stdlib.h> |
29 #include <stdlib.h> |
9 #include <string.h> |
30 #include <string.h> |
10 #include <stdarg.h> |
31 #include <stdarg.h> |
11 |
32 |
12 #include "string.h" |
33 #include "string.h" |
13 |
34 #include "allocator.h" |
14 sstr_t sstr(char *s) { |
35 |
|
36 sstr_t sstr(char *cstring) { |
15 sstr_t string; |
37 sstr_t string; |
16 string.ptr = s; |
38 string.ptr = cstring; |
17 string.length = strlen(s); |
39 string.length = strlen(cstring); |
18 return string; |
40 return string; |
19 } |
41 } |
20 |
42 |
21 sstr_t sstrn(char *s, size_t n) { |
43 sstr_t sstrn(char *cstring, size_t length) { |
22 sstr_t string; |
44 sstr_t string; |
23 string.ptr = s; |
45 string.ptr = cstring; |
24 string.length = n; |
46 string.length = length; |
25 return string; |
47 return string; |
26 } |
48 } |
27 |
49 |
28 size_t sstrnlen(size_t n, sstr_t s, ...) { |
50 size_t sstrnlen(size_t n, sstr_t s, ...) { |
29 va_list ap; |
51 va_list ap; |
30 size_t size = s.length; |
52 size_t size = s.length; |
31 va_start(ap, s); |
53 va_start(ap, s); |
32 |
54 |
33 for (int i=0;i<n-1;i++) { |
55 for (size_t i = 1 ; i < n ; i++) { |
34 sstr_t str = va_arg(ap, sstr_t); |
56 sstr_t str = va_arg(ap, sstr_t); |
35 size += str.length; |
57 size += str.length; |
36 } |
58 } |
37 va_end(ap); |
59 va_end(ap); |
38 |
60 |
39 return size; |
61 return size; |
40 } |
62 } |
41 |
63 |
42 sstr_t sstrcat(sstr_t s, ...) { |
64 sstr_t sstrncat(sstr_t s, size_t n, sstr_t c1, ...) { |
43 va_list ap; |
|
44 va_start(ap, s); |
|
45 s.ptr[0] = 0; |
|
46 |
|
47 sstr_t str = va_arg (ap, sstr_t); |
|
48 while (str.ptr != NULL) { |
|
49 s.ptr = strncat (s.ptr, str.ptr, s.length); |
|
50 str = va_arg (ap, sstr_t); |
|
51 } |
|
52 va_end(ap); |
|
53 |
|
54 return s; |
|
55 } |
|
56 |
|
57 sstr_t sstrncat(size_t n, sstr_t s, sstr_t c1, ...) { |
|
58 va_list ap; |
65 va_list ap; |
59 va_start(ap, c1); |
66 va_start(ap, c1); |
60 s.ptr[0] = 0; |
67 s.ptr[0] = 0; |
61 |
68 |
62 size_t len = s.length; |
69 size_t len = s.length; |
76 memcpy(ptr, str.ptr, cplen); |
83 memcpy(ptr, str.ptr, cplen); |
77 len -= cplen; |
84 len -= cplen; |
78 ptr += cplen; |
85 ptr += cplen; |
79 } |
86 } |
80 va_end(ap); |
87 va_end(ap); |
|
88 s.length = ptr - s.ptr; |
81 |
89 |
82 return s; |
90 return s; |
83 } |
91 } |
84 |
92 |
85 sstr_t sstrsubs(sstr_t s, size_t start) { |
93 sstr_t sstrsubs(sstr_t s, size_t start) { |
86 return sstrsubsl (s, start, s.length-start); |
94 return sstrsubsl (s, start, s.length-start); |
87 } |
95 } |
88 |
96 |
89 sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) { |
97 sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) { |
90 sstr_t new_sstr; |
98 sstr_t new_sstr; |
91 if (start < 0 || start >= s.length || length < 0) { |
99 if (start >= s.length) { |
92 return s; |
100 return s; |
93 } |
101 } |
94 if (length > s.length-start) { |
102 if (length > s.length-start) { |
95 length = s.length-start; |
103 length = s.length-start; |
96 } |
104 } |
97 new_sstr.ptr = &s.ptr[start]; |
105 new_sstr.ptr = &s.ptr[start]; |
98 new_sstr.length = length; |
106 new_sstr.length = length; |
99 return new_sstr; |
107 return new_sstr; |
100 } |
108 } |
101 |
109 |
|
110 sstr_t sstrchr(sstr_t s, int c) { |
|
111 for(size_t i=0;i<s.length;i++) { |
|
112 if(s.ptr[i] == c) { |
|
113 return sstrsubs(s, i); |
|
114 } |
|
115 } |
|
116 sstr_t n; |
|
117 n.ptr = NULL; |
|
118 n.length = 0; |
|
119 return n; |
|
120 } |
|
121 |
102 sstr_t* sstrsplit(sstr_t s, sstr_t d, size_t *n) { |
122 sstr_t* sstrsplit(sstr_t s, sstr_t d, size_t *n) { |
103 if (d.length == 0) { |
123 return sstrsplit_a(ucx_default_allocator(), s, d, n); |
|
124 } |
|
125 |
|
126 sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, size_t *n) { |
|
127 if (s.length == 0 || d.length == 0) { |
|
128 *n = -1; |
104 return NULL; |
129 return NULL; |
105 } |
130 } |
106 |
131 |
107 sstr_t* result; |
132 sstr_t* result; |
108 size_t nmax = *n; |
133 size_t nmax = *n; |
109 *n = 1; |
134 *n = 1; |
110 |
135 |
111 /* special case: exact match - no processing needed */ |
136 /* special case: exact match - no processing needed */ |
112 if (s.length == d.length && strncmp(s.ptr, d.ptr, s.length) == 0) { |
137 if (sstrcmp(s, d) == 0) { |
113 *n = 0; |
138 *n = 0; |
114 return NULL; |
139 return NULL; |
115 } |
140 } |
116 sstr_t sv = sstrdup(s); |
141 sstr_t sv = sstrdup(s); |
117 |
142 if (sv.length == 0) { |
118 for (int i = 0 ; i < s.length ; i++) { |
143 *n = -2; |
|
144 return NULL; |
|
145 } |
|
146 |
|
147 for (size_t i = 0 ; i < s.length ; i++) { |
119 if (sv.ptr[i] == d.ptr[0]) { |
148 if (sv.ptr[i] == d.ptr[0]) { |
120 _Bool match = 1; |
149 _Bool match = 1; |
121 for (int j = 1 ; j < d.length ; j++) { |
150 for (size_t j = 1 ; j < d.length ; j++) { |
122 if (j+i < s.length) { |
151 if (j+i < s.length) { |
123 match &= (sv.ptr[i+j] == d.ptr[j]); |
152 match &= (sv.ptr[i+j] == d.ptr[j]); |
124 } else { |
153 } else { |
125 match = 0; |
154 match = 0; |
126 break; |
155 break; |
127 } |
156 } |
128 } |
157 } |
129 if (match) { |
158 if (match) { |
130 (*n)++; |
159 (*n)++; |
131 for (int j = 0 ; j < d.length ; j++) { |
160 for (size_t j = 0 ; j < d.length ; j++) { |
132 sv.ptr[i+j] = 0; |
161 sv.ptr[i+j] = 0; |
133 } |
162 } |
134 i += d.length; |
163 i += d.length; |
135 } |
164 } |
136 } |
165 } |
137 if ((*n) == nmax) break; |
166 if ((*n) == nmax) break; |
138 } |
167 } |
139 result = (sstr_t*) malloc(sizeof(sstr_t) * (*n)); |
168 result = (sstr_t*) allocator->malloc(allocator->pool, sizeof(sstr_t)*(*n)); |
140 |
169 |
141 char *pptr = sv.ptr; |
170 if (result) { |
142 for (int i = 0 ; i < *n ; i++) { |
171 char *pptr = sv.ptr; |
143 size_t l = strlen(pptr); |
172 for (size_t i = 0 ; i < *n ; i++) { |
144 char* ptr = (char*) malloc(l + 1); |
173 size_t l = strlen(pptr); |
145 memcpy(ptr, pptr, l); |
174 char* ptr = (char*) allocator->malloc(allocator->pool, l + 1); |
146 ptr[l] = 0; |
175 memcpy(ptr, pptr, l); |
147 |
176 ptr[l] = 0; |
148 result[i] = sstrn(ptr, l); |
177 |
149 pptr += l + d.length; |
178 result[i] = sstrn(ptr, l); |
150 } |
179 pptr += l + d.length; |
151 |
180 } |
|
181 } else { |
|
182 *n = -2; |
|
183 } |
|
184 |
152 free(sv.ptr); |
185 free(sv.ptr); |
153 |
186 |
154 return result; |
187 return result; |
155 } |
188 } |
156 |
189 |
157 int sstrcmp(sstr_t s1, sstr_t s2) { |
190 int sstrcmp(sstr_t s1, sstr_t s2) { |
158 return strncmp(s1.ptr, s2.ptr, s1.length>s2.length ? s2.length: s1.length); |
191 if (s1.length == s2.length) { |
|
192 return memcmp(s1.ptr, s2.ptr, s1.length); |
|
193 } else if (s1.length > s2.length) { |
|
194 return 1; |
|
195 } else { |
|
196 return -1; |
|
197 } |
159 } |
198 } |
160 |
199 |
161 sstr_t sstrdup(sstr_t s) { |
200 sstr_t sstrdup(sstr_t s) { |
|
201 return sstrdup_a(ucx_default_allocator(), s); |
|
202 } |
|
203 |
|
204 sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t s) { |
162 sstr_t newstring; |
205 sstr_t newstring; |
163 newstring.ptr = (char*) malloc(s.length + 1); |
206 newstring.ptr = (char*)allocator->malloc(allocator->pool, s.length + 1); |
164 if (newstring.ptr != NULL) { |
207 if (newstring.ptr) { |
165 newstring.length = s.length; |
208 newstring.length = s.length; |
166 newstring.ptr[newstring.length] = 0; |
209 newstring.ptr[newstring.length] = 0; |
167 |
210 |
168 memcpy(newstring.ptr, s.ptr, s.length); |
211 memcpy(newstring.ptr, s.ptr, s.length); |
169 } |
212 } else { |
170 |
213 newstring.length = 0; |
|
214 } |
|
215 |
171 return newstring; |
216 return newstring; |
172 } |
217 } |
|
218 |
|
219 sstr_t sstrtrim(sstr_t string) { |
|
220 sstr_t newstr = string; |
|
221 if (string.length == 0) { |
|
222 return newstr; |
|
223 } |
|
224 |
|
225 size_t i; |
|
226 for(i=0;i<string.length;i++) { |
|
227 char c = string.ptr[i]; |
|
228 if(c > 32) { |
|
229 break; |
|
230 } |
|
231 } |
|
232 newstr.ptr = &string.ptr[i]; |
|
233 newstr.length = string.length - i; |
|
234 |
|
235 if(newstr.length == 0) { |
|
236 return newstr; |
|
237 } |
|
238 |
|
239 i = newstr.length - 1; |
|
240 for(;;) { |
|
241 char c = newstr.ptr[i]; |
|
242 if(c > 32) { |
|
243 break; |
|
244 } |
|
245 if(i > 0) { |
|
246 i--; |
|
247 } else { |
|
248 break; |
|
249 } |
|
250 } |
|
251 newstr.length = i + 1; |
|
252 |
|
253 return newstr; |
|
254 } |