optimize the interface with python
[liba.git] / src / str.c
blob320193904163dd6e8e319e47229416953236ae1f
1 #if defined(_MSC_VER)
2 #if !defined _CRT_SECURE_NO_WARNINGS
3 #define _CRT_SECURE_NO_WARNINGS /* NOLINT */
4 #endif /* _CRT_SECURE_NO_WARNINGS */
5 #endif /* _MSC_VER */
6 #include "a/str.h"
8 a_str *a_str_new(void)
10 a_str *const ctx = (a_str *)a_alloc(A_NULL, sizeof(a_str));
11 if (ctx) { a_str_ctor(ctx); }
12 return ctx;
15 void a_str_die(a_str *ctx)
17 if (ctx)
19 a_str_dtor(ctx);
20 a_alloc(ctx, 0);
24 void a_str_ctor(a_str *ctx)
26 ctx->ptr_ = A_NULL;
27 ctx->num_ = 0;
28 ctx->mem_ = 0;
31 void a_str_dtor(a_str *ctx)
33 if (ctx->ptr_)
35 a_alloc(ctx->ptr_, 0);
36 ctx->ptr_ = A_NULL;
38 ctx->num_ = 0;
39 ctx->mem_ = 0;
42 int a_str_init(a_str *ctx, void const *pdata, a_size nbyte)
44 ctx->num_ = nbyte;
45 ctx->mem_ = ctx->num_ + 1;
46 ctx->mem_ = a_size_up(sizeof(void *), ctx->mem_);
47 ctx->ptr_ = (char *)a_alloc(A_NULL, ctx->mem_);
48 if (a_unlikely(!ctx->ptr_)) { return A_FAILURE; }
49 if (pdata && nbyte)
51 a_copy(ctx->ptr_, pdata, nbyte);
53 ctx->ptr_[ctx->num_] = 0;
54 return A_SUCCESS;
57 int a_str_copy(a_str *ctx, a_str const *obj)
59 return a_str_init(ctx, obj->ptr_, obj->num_);
62 void a_str_move(a_str *ctx, a_str *obj)
64 a_copy(ctx, obj, sizeof(*obj));
65 a_zero(obj, sizeof(*obj));
68 char *a_str_exit(a_str *ctx)
70 char *const str = ctx->ptr_;
71 if (ctx->ptr_)
73 ctx->ptr_[ctx->num_] = 0;
74 ctx->ptr_ = A_NULL;
76 ctx->num_ = 0;
77 ctx->mem_ = 0;
78 return str;
81 int a_str_cmp(a_str const *lhs, a_str const *rhs)
83 int ok = 0;
84 if (lhs->ptr_ && rhs->ptr_)
86 ok = memcmp(lhs->ptr_, rhs->ptr_, A_MIN(lhs->num_, rhs->num_));
87 if (ok) { return ok; }
89 if (lhs->num_ == rhs->num_) { return 0; }
90 return lhs->num_ < rhs->num_ ? -1 : +1;
93 int a_str_alloc_(a_str *ctx, a_size mem)
95 char *ptr;
96 mem = a_size_up(sizeof(void *), mem);
97 ptr = (char *)a_alloc(ctx->ptr_, mem);
98 if (a_unlikely(!ptr && mem)) { return A_FAILURE; }
99 ctx->ptr_ = ptr;
100 ctx->mem_ = mem;
101 return A_SUCCESS;
104 int a_str_alloc(a_str *ctx, a_size mem)
106 return ctx->mem_ < mem ? a_str_alloc_(ctx, mem) : A_SUCCESS;
109 int a_str_getc_(a_str *ctx)
111 int c = ~0;
112 if (ctx->num_)
114 c = (int)ctx->ptr_[--ctx->num_];
116 return c;
119 int a_str_getc(a_str *ctx)
121 int c = ~0;
122 if (ctx->num_)
124 c = (int)ctx->ptr_[--ctx->num_];
125 ctx->ptr_[ctx->num_] = 0;
127 return c;
130 int a_str_putc_(a_str *ctx, int c)
132 if (a_unlikely(a_str_alloc(ctx, ctx->num_ + 1))) { return ~0; }
133 ctx->ptr_[ctx->num_++] = (char)c;
134 return c;
137 int a_str_putc(a_str *ctx, int c)
139 if (a_unlikely(a_str_alloc(ctx, ctx->num_ + 2))) { return ~0; }
140 ctx->ptr_[ctx->num_++] = (char)c;
141 ctx->ptr_[ctx->num_] = 0;
142 return c;
145 a_size a_str_getn_(a_str *ctx, void *pdata, a_size nbyte)
147 if (nbyte > ctx->num_) { nbyte = ctx->num_; }
148 if (pdata && nbyte)
150 ctx->num_ -= nbyte;
151 a_copy(pdata, ctx->ptr_ + ctx->num_, nbyte);
153 return nbyte;
156 a_size a_str_getn(a_str *ctx, void *pdata, a_size nbyte)
158 if (nbyte > ctx->num_) { nbyte = ctx->num_; }
159 if (pdata && nbyte)
161 ctx->num_ -= nbyte;
162 a_copy(pdata, ctx->ptr_ + ctx->num_, nbyte);
163 ctx->ptr_[ctx->num_] = 0;
165 return nbyte;
168 int a_str_putn_(a_str *ctx, void const *pdata, a_size nbyte)
170 if (pdata && nbyte)
172 if (a_unlikely(a_str_alloc(ctx, ctx->num_ + nbyte))) { return A_FAILURE; }
173 a_copy(ctx->ptr_ + ctx->num_, pdata, nbyte);
174 ctx->num_ += nbyte;
176 return A_SUCCESS;
179 int a_str_putn(a_str *ctx, void const *pdata, a_size nbyte)
181 if (pdata && nbyte)
183 if (a_unlikely(a_str_alloc(ctx, ctx->num_ + nbyte + 1))) { return A_FAILURE; }
184 a_copy(ctx->ptr_ + ctx->num_, pdata, nbyte);
185 ctx->num_ += nbyte;
186 ctx->ptr_[ctx->num_] = 0;
188 return A_SUCCESS;
191 int a_str_puts_(a_str *ctx, void const *str)
193 return a_str_putn_(ctx, str, strlen((char const *)str));
196 int a_str_puts(a_str *ctx, void const *str)
198 return a_str_putn(ctx, str, strlen((char const *)str));
201 int a_str_cat_(a_str *ctx, a_str const *obj)
203 return a_str_putn_(ctx, obj->ptr_, obj->num_);
206 int a_str_cat(a_str *ctx, a_str const *obj)
208 return a_str_putn(ctx, obj->ptr_, obj->num_);
211 #include <stdio.h>
213 int a_str_putf_(a_str *ctx, char const *fmt, va_list va)
215 int res;
216 va_list ap;
217 a_size mem;
218 char *ptr = ctx->ptr_ ? ctx->ptr_ + ctx->num_ : ctx->ptr_;
219 va_copy(ap, va);
220 mem = ctx->mem_ - ctx->num_;
221 res = vsnprintf(ptr, mem, fmt, ap);
222 mem = ctx->num_ + (size_t)(res + 1);
223 va_end(ap);
224 if (mem > ctx->mem_)
226 if (a_unlikely(a_str_alloc_(ctx, mem))) { return 0; }
227 va_copy(ap, va);
228 ptr = ctx->ptr_ + ctx->num_;
229 mem = ctx->mem_ - ctx->num_;
230 res = vsnprintf(ptr, mem, fmt, ap);
231 va_end(ap);
233 if (res > 0) { ctx->num_ += (size_t)res; }
234 return res;
237 int a_str_putf(a_str *ctx, char const *fmt, ...)
239 int res;
240 va_list va;
241 va_start(va, fmt);
242 res = a_str_putf_(ctx, fmt, va);
243 va_end(va);
244 return res;
247 #include "a/utf.h"
249 a_size a_str_utflen(a_str const *ctx)
251 a_size length = 0;
252 if (ctx->num_)
254 char const *head = ctx->ptr_;
255 char const *const tail = head + ctx->num_;
256 unsigned int offset = a_utf_decode(head, A_NULL);
257 for (; offset; offset = a_utf_decode(head, A_NULL))
259 ++length;
260 head += offset;
261 if (head >= tail) { break; }
264 return length;