fix atan2,rename {hypot,hypot3} to {norm2,norm3}
[liba.git] / src / str.c
blob49b75df71bd945c229fa9a0c7dd8cfa2a7124423
1 #if !defined _CRT_SECURE_NO_WARNINGS && defined(_MSC_VER)
2 #define _CRT_SECURE_NO_WARNINGS /* NOLINT */
3 #endif /* _CRT_SECURE_NO_WARNINGS */
4 #if !defined _GNU_SOURCE && defined(__linux__)
5 #define _GNU_SOURCE 1
6 #endif /* _GNU_SOURCE */
7 #include "a/str.h"
9 a_str *a_str_new(void)
11 a_str *const ctx = (a_str *)a_alloc(A_NULL, sizeof(a_str));
12 if (ctx) { a_str_ctor(ctx); }
13 return ctx;
16 void a_str_die(a_str *ctx)
18 if (ctx)
20 a_str_dtor(ctx);
21 a_alloc(ctx, 0);
25 void a_str_ctor(a_str *ctx)
27 ctx->ptr_ = A_NULL;
28 ctx->num_ = 0;
29 ctx->mem_ = 0;
32 void a_str_dtor(a_str *ctx)
34 if (ctx->ptr_)
36 a_alloc(ctx->ptr_, 0);
37 ctx->ptr_ = A_NULL;
39 ctx->num_ = 0;
40 ctx->mem_ = 0;
43 int a_str_copy(a_str *ctx, a_str const *obj)
45 int ok;
46 a_str_ctor(ctx);
47 ok = a_str_alloc_(ctx, obj->num_ + 1);
48 if (ok == A_SUCCESS)
50 if (obj->num_) { a_copy(ctx->ptr_, obj->ptr_, obj->num_); }
51 ctx->ptr_[obj->num_] = 0;
52 ctx->num_ = obj->num_;
54 return ok;
57 void a_str_move(a_str *ctx, a_str *obj)
59 a_copy(ctx, obj, sizeof(*obj));
60 a_zero(obj, sizeof(*obj));
63 char *a_str_exit(a_str *ctx)
65 char *const str = ctx->ptr_;
66 if (ctx->ptr_)
68 ctx->ptr_[ctx->num_] = 0;
69 ctx->ptr_ = A_NULL;
71 ctx->num_ = 0;
72 ctx->mem_ = 0;
73 return str;
76 int a_str_alloc_(a_str *ctx, a_size mem)
78 char *ptr;
79 mem = a_size_up(sizeof(void *), mem);
80 ptr = (char *)a_alloc(ctx->ptr_, mem);
81 if (ptr || mem == 0)
83 ctx->ptr_ = ptr;
84 ctx->mem_ = mem;
85 return A_SUCCESS;
87 return A_FAILURE;
90 int a_str_alloc(a_str *ctx, a_size mem)
92 if (mem > ctx->mem_)
94 return a_str_alloc_(ctx, mem);
96 return A_SUCCESS;
99 int a_str_cmp_(void const *p0, a_size n0, void const *p1, a_size n1)
101 int ok;
102 if (p0 && p1)
104 ok = memcmp(p0, p1, A_MIN(n0, n1));
105 if (ok) { return ok; }
107 return (n0 > n1) - (n0 < n1);
110 int a_str_cmp(a_str const *ctx, a_str const *str)
112 return a_str_cmp_(ctx->ptr_, ctx->num_, str->ptr_, str->num_);
115 int a_str_cmpn(a_str const *ctx, void const *pdata, a_size nbyte)
117 return a_str_cmp_(ctx->ptr_, ctx->num_, pdata, nbyte);
120 int a_str_cmps(a_str const *ctx, void const *str)
122 return a_str_cmp_(ctx->ptr_, ctx->num_, str, strlen((char const *)str));
125 int a_str_getc_(a_str *ctx)
127 int c = ~0;
128 if (ctx->num_)
130 c = (int)ctx->ptr_[--ctx->num_];
132 return c;
135 int a_str_getc(a_str *ctx)
137 int c = ~0;
138 if (ctx->num_)
140 c = (int)ctx->ptr_[--ctx->num_];
141 ctx->ptr_[ctx->num_] = 0;
143 return c;
146 int a_str_putc_(a_str *ctx, int c)
148 if (a_str_alloc(ctx, ctx->num_ + 1) == A_SUCCESS)
150 ctx->ptr_[ctx->num_++] = (char)c;
151 return c;
153 return ~0;
156 int a_str_putc(a_str *ctx, int c)
158 if (a_str_alloc(ctx, ctx->num_ + 2) == A_SUCCESS)
160 ctx->ptr_[ctx->num_++] = (char)c;
161 ctx->ptr_[ctx->num_] = 0;
162 return c;
164 return ~0;
167 a_size a_str_getn_(a_str *ctx, void *pdata, a_size nbyte)
169 if (nbyte > ctx->num_) { nbyte = ctx->num_; }
170 if (nbyte)
172 ctx->num_ -= nbyte;
173 if (pdata) { a_copy(pdata, ctx->ptr_ + ctx->num_, nbyte); }
175 return nbyte;
178 a_size a_str_getn(a_str *ctx, void *pdata, a_size nbyte)
180 if (nbyte > ctx->num_) { nbyte = ctx->num_; }
181 if (nbyte)
183 ctx->num_ -= nbyte;
184 if (pdata) { a_copy(pdata, ctx->ptr_ + ctx->num_, nbyte); }
185 ctx->ptr_[ctx->num_] = 0;
187 return nbyte;
190 int a_str_setn_(a_str *ctx, void const *pdata, a_size nbyte)
192 int ok = a_str_alloc(ctx, nbyte);
193 if (ok == A_SUCCESS && nbyte)
195 a_copy(ctx->ptr_, pdata, nbyte);
196 ctx->num_ = nbyte;
198 return ok;
201 int a_str_putn_(a_str *ctx, void const *pdata, a_size nbyte)
203 int ok = a_str_alloc(ctx, ctx->num_ + nbyte);
204 if (ok == A_SUCCESS && nbyte)
206 a_copy(ctx->ptr_ + ctx->num_, pdata, nbyte);
207 ctx->num_ += nbyte;
209 return ok;
212 int a_str_setn(a_str *ctx, void const *pdata, a_size nbyte)
214 int ok = a_str_alloc(ctx, nbyte + 1);
215 if (ok == A_SUCCESS)
217 if (nbyte) { a_copy(ctx->ptr_, pdata, nbyte); }
218 ctx->ptr_[nbyte] = 0;
219 ctx->num_ = nbyte;
221 return ok;
224 int a_str_putn(a_str *ctx, void const *pdata, a_size nbyte)
226 int ok = a_str_alloc(ctx, ctx->num_ + nbyte + 1);
227 if (ok == A_SUCCESS)
229 if (nbyte)
231 a_copy(ctx->ptr_ + ctx->num_, pdata, nbyte);
232 ctx->num_ += nbyte;
234 ctx->ptr_[ctx->num_] = 0;
236 return ok;
239 int a_str_sets_(a_str *ctx, void const *str)
241 return a_str_setn_(ctx, str, strlen((char const *)str));
243 int a_str_sets(a_str *ctx, void const *str)
245 return a_str_setn(ctx, str, strlen((char const *)str));
248 int a_str_puts_(a_str *ctx, void const *str)
250 return a_str_putn_(ctx, str, strlen((char const *)str));
252 int a_str_puts(a_str *ctx, void const *str)
254 return a_str_putn(ctx, str, strlen((char const *)str));
257 int a_str_set_(a_str *ctx, a_str const *obj)
259 return a_str_setn_(ctx, obj->ptr_, obj->num_);
261 int a_str_set(a_str *ctx, a_str const *obj)
263 return a_str_setn(ctx, obj->ptr_, obj->num_);
266 int a_str_put_(a_str *ctx, a_str const *obj)
268 return a_str_putn_(ctx, obj->ptr_, obj->num_);
270 int a_str_put(a_str *ctx, a_str const *obj)
272 return a_str_putn(ctx, obj->ptr_, obj->num_);
275 #if !defined va_copy && \
276 (A_PREREQ_GNUC(3, 0) || __has_builtin(__builtin_va_copy))
277 #define va_copy(d, s) __builtin_va_copy(d, s)
278 #elif !defined va_copy
279 #define va_copy(d, s) ((d) = (s))
280 #endif /* va_copy */
281 #include <stdio.h>
283 int a_str_setv(a_str *ctx, char const *fmt, va_list va)
285 int res;
286 va_list ap;
287 va_copy(ap, va);
288 res = vsnprintf(ctx->ptr_, ctx->mem_, fmt, ap);
289 va_end(ap);
290 if ((a_size)res + 1 > ctx->mem_)
292 if (A_UNLIKELY(a_str_alloc_(ctx, (a_size)res + 1))) { return 0; }
293 res = vsnprintf(ctx->ptr_, ctx->mem_, fmt, va);
295 if (res >= 0) { ctx->num_ = (a_size)res; }
296 return res;
299 int a_str_putv(a_str *ctx, char const *fmt, va_list va)
301 int res;
302 va_list ap;
303 a_size mem;
304 char *ptr = ctx->ptr_;
305 if (ptr) { ptr += ctx->num_; }
306 mem = ctx->mem_ - ctx->num_;
307 va_copy(ap, va);
308 res = vsnprintf(ptr, mem, fmt, ap);
309 va_end(ap);
310 mem = ctx->num_ + (a_size)(res + 1);
311 if (mem > ctx->mem_)
313 if (A_UNLIKELY(a_str_alloc_(ctx, mem))) { return 0; }
314 ptr = ctx->ptr_ + ctx->num_;
315 mem = ctx->mem_ - ctx->num_;
316 res = vsnprintf(ptr, mem, fmt, va);
318 if (res > 0) { ctx->num_ += (a_size)res; }
319 return res;
322 int a_str_setf(a_str *ctx, char const *fmt, ...)
324 int res;
325 va_list va;
326 va_start(va, fmt);
327 res = a_str_setv(ctx, fmt, va);
328 va_end(va);
329 return res;
332 int a_str_putf(a_str *ctx, char const *fmt, ...)
334 int res;
335 va_list va;
336 va_start(va, fmt);
337 res = a_str_putv(ctx, fmt, va);
338 va_end(va);
339 return res;
342 #include "a/utf.h"
344 a_size a_str_utflen(a_str const *ctx)
346 a_size length = 0;
347 if (ctx->num_)
349 char const *head = ctx->ptr_;
350 char const *const tail = head + ctx->num_;
351 unsigned int offset = a_utf_decode(head, A_NULL);
352 for (; offset; offset = a_utf_decode(head, A_NULL))
354 ++length;
355 head += offset;
356 if (head >= tail) { break; }
359 return length;