Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

first attempt at support for extended capabilities

  • Loading branch information...
commit e11128debcac6c4bff7a5b7d66ca74d2168ed5c3 1 parent 33831e5
mauke authored

Showing 2 changed files with 501 additions and 227 deletions. Show diff stats Hide diff stats

  1. +473 215 unibilium.c
  2. +28 12 unibilium.h
688 unibilium.c
@@ -12,12 +12,62 @@
12 12 #include <string.h>
13 13 #include <stdlib.h>
14 14
  15 +#define ASSERT_RETURN(COND, VAL) do { \
  16 + assert(COND); \
  17 + if (!(COND)) return VAL; \
  18 +} while (0)
  19 +
  20 +#define ASSERT_RETURN_(COND) ASSERT_RETURN(COND, )
  21 +
15 22 #define COUNTOF(a) (sizeof (a) / sizeof *(a))
16 23
17 24 #define NCONTAINERS(n, csize) (((n) - 1) / (csize) + 1u)
18 25
  26 +#define SIZE_ERR ((size_t)-1)
  27 +
19 28 #define MAX15BITS 0x7fff
20 29
  30 +#define DYNARR(W, X) DynArr_ ## W ## _ ## X
  31 +#define DYNARR_T(W) DYNARR(W, t)
  32 +#define DEFDYNARRAY(T, W) \
  33 + typedef struct { T (*data); size_t used, size; } DYNARR_T(W); \
  34 + static void DYNARR(W, init)(DYNARR_T(W) *const d) { \
  35 + d->data = NULL; \
  36 + d->used = d->size = 0; \
  37 + } \
  38 + static void DYNARR(W, free)(DYNARR_T(W) *const d) { \
  39 + free(d->data); \
  40 + DYNARR(W, init)(d); \
  41 + } \
  42 + static int DYNARR(W, ensure_slots)(DYNARR_T(W) *const d, const size_t n) { \
  43 + size_t k = d->size; \
  44 + while (d->used + n > k) { \
  45 + k = next_alloc(k); \
  46 + } \
  47 + if (k > d->size) { \
  48 + T (*const p) = realloc(d->data, k * sizeof *p); \
  49 + if (!p) { \
  50 + return 0; \
  51 + } \
  52 + d->data = p; \
  53 + d->size = k; \
  54 + } \
  55 + return 1; \
  56 + } \
  57 + static int DYNARR(W, ensure_slot)(DYNARR_T(W) *const d) { \
  58 + return DYNARR(W, ensure_slots)(d, 1); \
  59 + } \
  60 + static void DYNARR(W, init)(DYNARR_T(W) *)
  61 +
  62 +static size_t next_alloc(size_t n) {
  63 + return n * 3 / 2 + 5;
  64 +}
  65 +
  66 +DEFDYNARRAY(unsigned char, bool);
  67 +DEFDYNARRAY(short, num);
  68 +DEFDYNARRAY(const char *, str);
  69 +
  70 +
21 71 enum {MAGIC = 0432};
22 72
23 73 struct unibi_term {
@@ -29,39 +79,15 @@ struct unibi_term {
29 79 const char *strs[unibi_string_end_ - unibi_string_begin_ - 1];
30 80 char *alloc;
31 81
32   -#if 0
33   - size_t ext_bsize;
34   - struct { const char *name; } *ext_bools;
35   - size_t ext_nsize;
36   - struct { const char *name; short value; } *ext_nums;
37   - size_t ext_ssize;
38   - struct { const char *name; const char *value; } *ext_strs;
  82 + DYNARR_T(bool) ext_bools;
  83 + DYNARR_T(num) ext_nums;
  84 + DYNARR_T(str) ext_strs;
  85 + DYNARR_T(str) ext_names;
39 86 char *ext_alloc;
40   -#endif
41 87 };
42 88
43   -/* No extended terminfo attributes for me. term(5) says the extended header
44   - * consists of:
45   - * | (1) count of extended boolean capabilities
46   - * | (2) count of extended numeric capabilities
47   - * | (3) count of extended string capabilities
48   - * | (4) size of the extended string table in bytes.
49   - * | (5) last offset of the extended string table in bytes.
50   - *
51   - * I have no idea why (5) is necessary. From this description it seems like (5)
52   - * should always be (4) - 1. Looking at the ncurses source code I find that it
53   - * completely ignores (4). However, it treats (5) as the size of the string
54   - * table. Later on, (5) is used as the size of both an array A and the part of
55   - * A starting at some offset > 0. This looks obviously broken. In addition, the
56   - * function responsible for checking these bounds has an off-by-one error.
57   - * Finally, I don't actually have any terminfo files that use extended
58   - * capabilities on my system.
59   - *
60   - * In conclusion: The docs are vague, the source contradicts the docs (but is
61   - * buggy), and I have no data files to reverse engineer the format. Until this
62   - * changes, I have no idea what to do in this library; therefore I simply
63   - * ignore extended capabilities.
64   - */
  89 +#define ASSERT_EXT_NAMES(X) assert((X)->ext_names.used == (X)->ext_bools.used + (X)->ext_nums.used + (X)->ext_strs.used)
  90 +
65 91
66 92 static unsigned short get_ushort(const char *p) {
67 93 const unsigned char *q = (const unsigned char *)p;
@@ -91,6 +117,7 @@ static const char *off_of(const char *p, size_t n, short i) {
91 117
92 118 unibi_term *unibi_dummy(void) {
93 119 unibi_term *t;
  120 +
94 121 if (!(t = malloc(sizeof *t))) {
95 122 return NULL;
96 123 }
@@ -106,15 +133,11 @@ unibi_term *unibi_dummy(void) {
106 133 fill_1(t->nums, COUNTOF(t->nums));
107 134 fill_null(t->strs, COUNTOF(t->strs));
108 135
109   -#if 0
110   - t->ext_bsize = 0;
111   - t->ext_bools = NULL;
112   - t->ext_nsize = 0;
113   - t->ext_nums = NULL;
114   - t->ext_ssize = 0;
115   - t->ext_strs = NULL;
  136 + DYNARR(bool, init)(&t->ext_bools);
  137 + DYNARR(num, init)(&t->ext_nums);
  138 + DYNARR(str, init)(&t->ext_strs);
  139 + DYNARR(str, init)(&t->ext_names);
116 140 t->ext_alloc = NULL;
117   -#endif
118 141
119 142 return t;
120 143 }
@@ -123,16 +146,19 @@ static size_t mcount(const char *p, size_t n, char c) {
123 146 size_t r = 0;
124 147 while (n--) {
125 148 if (*p++ == c) {
126   - ++r;
  149 + r++;
127 150 }
128 151 }
129 152 return r;
130 153 }
131 154
  155 +static size_t size_max(size_t a, size_t b) {
  156 + return a >= b ? a : b;
  157 +}
  158 +
132 159 #define FAIL_IF_(c, e, f) do { if (c) { f; errno = (e); return NULL; } } while (0)
133 160 #define FAIL_IF(c, e) FAIL_IF_(c, e, (void)0)
134 161 #define DEL_FAIL_IF(c, e, x) FAIL_IF_(c, e, unibi_destroy(x))
135   -#define SOFT_FAIL_IF(c) if (!(c)) ; else break
136 162
137 163 unibi_term *unibi_from_mem(const char *p, size_t n) {
138 164 unibi_term *t = NULL;
@@ -189,19 +215,15 @@ unibi_term *unibi_from_mem(const char *p, size_t n) {
189 215 t->name = a;
190 216 }
191 217
192   -#if 0
193   - t->ext_bsize = 0;
194   - t->ext_bools = NULL;
195   - t->ext_nsize = 0;
196   - t->ext_nums = NULL;
197   - t->ext_ssize = 0;
198   - t->ext_strs = NULL;
  218 + DYNARR(bool, init)(&t->ext_bools);
  219 + DYNARR(num, init)(&t->ext_nums);
  220 + DYNARR(str, init)(&t->ext_strs);
  221 + DYNARR(str, init)(&t->ext_names);
199 222 t->ext_alloc = NULL;
200   -#endif
201 223
202 224 DEL_FAIL_IF(n < boollen, EFAULT, t);
203 225 memset(t->bools, '\0', sizeof t->bools);
204   - for (i = 0; i < boollen && i / CHAR_BIT < COUNTOF(t->bools); ++i) {
  226 + for (i = 0; i < boollen && i / CHAR_BIT < COUNTOF(t->bools); i++) {
205 227 if (p[i]) {
206 228 t->bools[i / CHAR_BIT] |= 1 << i % CHAR_BIT;
207 229 }
@@ -215,7 +237,7 @@ unibi_term *unibi_from_mem(const char *p, size_t n) {
215 237 }
216 238
217 239 DEL_FAIL_IF(n < numlen * 2u, EFAULT, t);
218   - for (i = 0; i < numlen && i < COUNTOF(t->nums); ++i) {
  240 + for (i = 0; i < numlen && i < COUNTOF(t->nums); i++) {
219 241 t->nums[i] = get_short(p + i * 2);
220 242 }
221 243 fill_1(t->nums + i, COUNTOF(t->nums) - i);
@@ -223,7 +245,7 @@ unibi_term *unibi_from_mem(const char *p, size_t n) {
223 245 n -= numlen * 2;
224 246
225 247 DEL_FAIL_IF(n < strslen * 2u, EFAULT, t);
226   - for (i = 0; i < strslen && i < COUNTOF(t->strs); ++i) {
  248 + for (i = 0; i < strslen && i < COUNTOF(t->strs); i++) {
227 249 t->strs[i] = off_of(strp, tablsz, get_short(p + i * 2));
228 250 }
229 251 fill_null(t->strs + i, COUNTOF(t->strs) - i);
@@ -232,39 +254,153 @@ unibi_term *unibi_from_mem(const char *p, size_t n) {
232 254
233 255 DEL_FAIL_IF(n < tablsz, EFAULT, t);
234 256 memcpy(strp, p, tablsz);
  257 + if (tablsz) {
  258 + strp[tablsz - 1] = '\0';
  259 + }
235 260 p += tablsz;
236 261 n -= tablsz;
237 262
238   -#if 0
239   - do {
240   - unsigned short extboollen, extnumlen, extstrslen, exttablsz, exttablend;
  263 + if (tablsz % 2 && n > 0) {
  264 + p += 1;
  265 + n -= 1;
  266 + }
241 267
242   - if (tablsz % 2 && n > 0) {
243   - p += 1;
244   - n -= 1;
245   - }
  268 + if (n >= 10) {
  269 + unsigned short extboollen, extnumlen, extstrslen, extofflen, exttablsz;
  270 + size_t extalllen;
246 271
247   - SOFT_FAIL_IF(n < 10);
248 272 extboollen = get_ushort(p + 0);
249 273 extnumlen = get_ushort(p + 2);
250 274 extstrslen = get_ushort(p + 4);
251   - exttablsz = get_ushort(p + 6);
252   - exttablend = get_ushort(p + 8);
253   - p += 10;
254   - n -= 10;
  275 + extofflen = get_ushort(p + 6);
  276 + exttablsz = get_ushort(p + 8);
  277 +
  278 + if (
  279 + extboollen <= MAX15BITS &&
  280 + extnumlen <= MAX15BITS &&
  281 + extstrslen <= MAX15BITS &&
  282 + extofflen <= MAX15BITS &&
  283 + exttablsz <= MAX15BITS
  284 + ) {
  285 + p += 10;
  286 + n -= 10;
  287 +
  288 + extalllen = 0;
  289 + extalllen += extboollen;
  290 + extalllen += extnumlen;
  291 + extalllen += extstrslen;
  292 +
  293 + DEL_FAIL_IF(extofflen != extalllen + extstrslen, EINVAL, t);
  294 +
  295 + DEL_FAIL_IF(
  296 + n <
  297 + extboollen +
  298 + extboollen % 2 +
  299 + extnumlen * 2 +
  300 + extstrslen * 2 +
  301 + extalllen * 2 +
  302 + exttablsz,
  303 + EFAULT,
  304 + t
  305 + );
  306 +
  307 + DEL_FAIL_IF(
  308 + !DYNARR(bool, ensure_slots)(&t->ext_bools, extboollen) ||
  309 + !DYNARR(num, ensure_slots)(&t->ext_nums, extnumlen) ||
  310 + !DYNARR(str, ensure_slots)(&t->ext_strs, extstrslen) ||
  311 + !DYNARR(str, ensure_slots)(&t->ext_names, extalllen) ||
  312 + (exttablsz && !(t->ext_alloc = malloc(exttablsz))),
  313 + ENOMEM,
  314 + t
  315 + );
  316 +
  317 + for (i = 0; i < extboollen; i++) {
  318 + t->ext_bools.data[i] = !!p[i];
  319 + }
  320 + t->ext_bools.used = extboollen;
  321 + p += extboollen;
  322 + n -= extboollen;
255 323
256   - SOFT_FAIL_IF(n < extboollen + extboollen % 2 + extnumlen * 2 + extstrslen * 2);
257   - } while (0);
258   -#endif
  324 + if (extboollen % 2) {
  325 + p += 1;
  326 + n -= 1;
  327 + }
  328 +
  329 + for (i = 0; i < extnumlen; i++) {
  330 + t->ext_nums.data[i] = get_short(p + i * 2);
  331 + }
  332 + t->ext_nums.used = extnumlen;
  333 + p += extnumlen * 2;
  334 + n -= extnumlen * 2;
  335 +
  336 + {
  337 + char *ext_alloc2;
  338 + size_t tblsz2;
  339 + const char *const tbl1 = p + extstrslen * 2 + extalllen * 2;
  340 + size_t s_max = 0, s_sum = 0;
  341 +
  342 + for (i = 0; i < extstrslen; i++) {
  343 + const short v = get_short(p + i * 2);
  344 + if (v < 0 || (unsigned short)v >= exttablsz) {
  345 + t->ext_strs.data[i] = NULL;
  346 + } else {
  347 + const char *start = tbl1 + v;
  348 + const char *end = memchr(start, '\0', exttablsz - v);
  349 + if (end) {
  350 + end++;
  351 + } else {
  352 + end = tbl1 + exttablsz;
  353 + }
  354 + s_sum += end - start;
  355 + s_max = size_max(s_max, end - tbl1);
  356 + t->ext_strs.data[i] = t->ext_alloc + v;
  357 + }
  358 + }
  359 + t->ext_strs.used = extstrslen;
  360 + p += extstrslen * 2;
  361 + n -= extstrslen * 2;
  362 +
  363 + DEL_FAIL_IF(s_max != s_sum, EINVAL, t);
  364 +
  365 + ext_alloc2 = t->ext_alloc + s_sum;
  366 + tblsz2 = exttablsz - s_sum;
  367 +
  368 + for (i = 0; i < extalllen; i++) {
  369 + const short v = get_short(p + i * 2);
  370 + DEL_FAIL_IF(v < 0 || (unsigned short)v >= tblsz2, EINVAL, t);
  371 + t->ext_names.data[i] = ext_alloc2 + v;
  372 + }
  373 + p += extalllen * 2;
  374 + n -= extalllen * 2;
  375 +
  376 + assert(p == tbl1);
  377 +
  378 + if (exttablsz) {
  379 + memcpy(t->ext_alloc, p, exttablsz);
  380 + t->ext_alloc[exttablsz - 1] = '\0';
  381 +
  382 + p += exttablsz;
  383 + n -= exttablsz;
  384 + }
  385 + }
  386 + }
  387 + }
259 388
260 389 return t;
261 390 }
262 391
  392 +#undef FAIL_IF
  393 +#undef FAIL_IF_
  394 +#undef DEL_FAIL_IF
  395 +
263 396 void unibi_destroy(unibi_term *t) {
264   -#if 0
  397 + DYNARR(bool, free)(&t->ext_bools);
  398 + DYNARR(num, free)(&t->ext_nums);
  399 + DYNARR(str, free)(&t->ext_strs);
  400 + DYNARR(str, free)(&t->ext_names);
265 401 free(t->ext_alloc);
266   - t->ext_alloc = (char *)":-S";
267   -#endif
  402 + t->ext_alloc = (char *)">_>";
  403 +
268 404 t->aliases = NULL;
269 405 free(t->alloc);
270 406 t->alloc = (char *)":-O";
@@ -289,15 +425,22 @@ static void put_short(char *p, short n) {
289 425 );
290 426 }
291 427
  428 +#define FAIL_INVAL_IF(c) if (c) { errno = EINVAL; return SIZE_ERR; } else (void)0
  429 +
292 430 size_t unibi_dump(const unibi_term *t, char *ptr, size_t n) {
293 431 size_t req, i;
294 432 size_t namlen, boollen, numlen, strslen, tablsz;
295   - char *p = ptr;
  433 + size_t ext_count, ext_tablsz1, ext_tablsz2;
  434 + char *p;
  435 +
  436 + ASSERT_EXT_NAMES(t);
296 437
297   - req = 12;
  438 + p = ptr;
  439 +
  440 + req = 2 + 5 * 2;
298 441
299 442 namlen = strlen(t->name) + 1;
300   - for (i = 0; t->aliases[i]; ++i) {
  443 + for (i = 0; t->aliases[i]; i++) {
301 444 namlen += strlen(t->aliases[i]) + 1;
302 445 }
303 446 req += namlen;
@@ -307,7 +450,7 @@ size_t unibi_dump(const unibi_term *t, char *ptr, size_t n) {
307 450 break;
308 451 }
309 452 }
310   - ++i;
  453 + i++;
311 454 boollen = i;
312 455 req += boollen;
313 456
@@ -320,7 +463,7 @@ size_t unibi_dump(const unibi_term *t, char *ptr, size_t n) {
320 463 break;
321 464 }
322 465 }
323   - ++i;
  466 + i++;
324 467 numlen = i;
325 468 req += numlen * 2;
326 469
@@ -329,7 +472,7 @@ size_t unibi_dump(const unibi_term *t, char *ptr, size_t n) {
329 472 break;
330 473 }
331 474 }
332   - ++i;
  475 + i++;
333 476 strslen = i;
334 477 req += strslen * 2;
335 478
@@ -341,9 +484,48 @@ size_t unibi_dump(const unibi_term *t, char *ptr, size_t n) {
341 484 }
342 485 req += tablsz;
343 486
344   - if (tablsz > MAX15BITS) {
345   - errno = EINVAL;
346   - return ~(size_t)0;
  487 + FAIL_INVAL_IF(tablsz > MAX15BITS);
  488 +
  489 + FAIL_INVAL_IF(t->ext_bools.used > MAX15BITS);
  490 + FAIL_INVAL_IF(t->ext_nums.used > MAX15BITS);
  491 + FAIL_INVAL_IF(t->ext_strs.used > MAX15BITS);
  492 +
  493 + ext_tablsz1 = ext_tablsz2 = 0;
  494 +
  495 + ext_count = t->ext_bools.used + t->ext_nums.used + t->ext_strs.used;
  496 + assert(ext_count == t->ext_names.used);
  497 +
  498 + if (ext_count) {
  499 + if (req % 2) {
  500 + req += 1;
  501 + }
  502 +
  503 + req += 5 * 2;
  504 +
  505 + req += t->ext_bools.used;
  506 + if (req % 2) {
  507 + req += 1;
  508 + }
  509 +
  510 + req += t->ext_nums.used * 2;
  511 +
  512 + req += t->ext_strs.used * 2;
  513 +
  514 + req += ext_count * 2;
  515 +
  516 + for (i = 0; i < t->ext_strs.used; i++) {
  517 + ext_tablsz1 += strlen(t->ext_strs.data[i]) + 1;
  518 + }
  519 + FAIL_INVAL_IF(ext_tablsz1 > MAX15BITS);
  520 + req += ext_tablsz1;
  521 +
  522 + for (i = 0; i < t->ext_names.used; i++) {
  523 + ext_tablsz2 += strlen(t->ext_names.data[i]) + 1;
  524 + }
  525 + FAIL_INVAL_IF(ext_tablsz2 > MAX15BITS);
  526 + req += ext_tablsz2;
  527 +
  528 + FAIL_INVAL_IF(ext_tablsz1 + ext_tablsz2 > MAX15BITS);
347 529 }
348 530
349 531 if (req > n) {
@@ -359,7 +541,7 @@ size_t unibi_dump(const unibi_term *t, char *ptr, size_t n) {
359 541 put_ushort(p + 10, tablsz);
360 542 p += 12;
361 543
362   - for (i = 0; t->aliases[i]; ++i) {
  544 + for (i = 0; t->aliases[i]; i++) {
363 545 size_t k = strlen(t->aliases[i]);
364 546 memcpy(p, t->aliases[i], k);
365 547 p += k;
@@ -371,7 +553,7 @@ size_t unibi_dump(const unibi_term *t, char *ptr, size_t n) {
371 553 p += k;
372 554 }
373 555
374   - for (i = 0; i < boollen; ++i) {
  556 + for (i = 0; i < boollen; i++) {
375 557 *p++ = t->bools[i / UCHAR_MAX] >> i % UCHAR_MAX & 1;
376 558 }
377 559
@@ -379,7 +561,7 @@ size_t unibi_dump(const unibi_term *t, char *ptr, size_t n) {
379 561 *p++ = '\0';
380 562 }
381 563
382   - for (i = 0; i < numlen; ++i) {
  564 + for (i = 0; i < numlen; i++) {
383 565 put_short(p, t->nums[i]);
384 566 p += 2;
385 567 }
@@ -388,7 +570,7 @@ size_t unibi_dump(const unibi_term *t, char *ptr, size_t n) {
388 570 char *const tbl = p + strslen * 2;
389 571 size_t off = 0;
390 572
391   - for (i = 0; i < strslen; ++i) {
  573 + for (i = 0; i < strslen; i++) {
392 574 if (!t->strs[i]) {
393 575 put_short(p, -1);
394 576 p += 2;
@@ -408,6 +590,65 @@ size_t unibi_dump(const unibi_term *t, char *ptr, size_t n) {
408 590 p += off;
409 591 }
410 592
  593 + if (ext_count) {
  594 + if ((p - ptr) % 2) {
  595 + *p++ = '\0';
  596 + }
  597 +
  598 + put_ushort(p + 0, t->ext_bools.used);
  599 + put_ushort(p + 2, t->ext_nums.used);
  600 + put_ushort(p + 4, t->ext_strs.used);
  601 + put_ushort(p + 6, t->ext_strs.used + ext_count);
  602 + put_ushort(p + 8, ext_tablsz1 + ext_tablsz2);
  603 + p += 10;
  604 +
  605 + memcpy(p, t->ext_bools.data, t->ext_bools.used);
  606 + p += t->ext_bools.used;
  607 +
  608 + if (t->ext_bools.used % 2) {
  609 + *p++ = '\0';
  610 + }
  611 +
  612 + for (i = 0; i < t->ext_nums.used; i++) {
  613 + put_short(p, t->ext_nums.data[i]);
  614 + p += 2;
  615 + }
  616 +
  617 + {
  618 + char *const tbl1 = p + (t->ext_strs.used + ext_count) * 2;
  619 + char *const tbl2 = tbl1 + ext_tablsz1;
  620 + size_t off = 0;
  621 +
  622 + for (i = 0; i < t->ext_strs.used; i++) {
  623 + const char *const s = t->ext_strs.data[i];
  624 + const size_t k = strlen(s) + 1;
  625 + assert(off < MAX15BITS);
  626 + put_ushort(p, off);
  627 + p += 2;
  628 + memcpy(tbl1 + off, s, k);
  629 + off += k;
  630 + }
  631 +
  632 + assert(off == ext_tablsz1);
  633 + assert(p + ext_count * 2 == tbl1);
  634 +
  635 + off = 0;
  636 + for (i = 0; i < t->ext_names.used; i++) {
  637 + const char *const s = t->ext_names.data[i];
  638 + const size_t k = strlen(s) + 1;
  639 + assert(off < MAX15BITS);
  640 + put_ushort(p, off);
  641 + p += 2;
  642 + memcpy(tbl2 + off, s, k);
  643 + off += k;
  644 + }
  645 +
  646 + assert(off == ext_tablsz2);
  647 + assert(p == tbl1);
  648 + p += ext_tablsz1 + ext_tablsz2;
  649 + }
  650 + }
  651 +
411 652 assert((size_t)(p - ptr) == req);
412 653
413 654 return req;
@@ -431,20 +672,14 @@ void unibi_set_aliases(unibi_term *t, const char **a) {
431 672
432 673 int unibi_get_bool(const unibi_term *t, enum unibi_boolean v) {
433 674 size_t i;
434   - assert(v > unibi_boolean_begin_ && v < unibi_boolean_end_);
435   - if (v <= unibi_boolean_begin_ || v >= unibi_boolean_end_) {
436   - return -1;
437   - }
  675 + ASSERT_RETURN(v > unibi_boolean_begin_ && v < unibi_boolean_end_, -1);
438 676 i = v - unibi_boolean_begin_ - 1;
439 677 return t->bools[i / CHAR_BIT] >> i % CHAR_BIT & 1;
440 678 }
441 679
442 680 void unibi_set_bool(unibi_term *t, enum unibi_boolean v, int x) {
443 681 size_t i;
444   - assert(v > unibi_boolean_begin_ && v < unibi_boolean_end_);
445   - if (v <= unibi_boolean_begin_ || v >= unibi_boolean_end_) {
446   - return;
447   - }
  682 + ASSERT_RETURN_(v > unibi_boolean_begin_ && v < unibi_boolean_end_);
448 683 i = v - unibi_boolean_begin_ - 1;
449 684 if (x) {
450 685 t->bools[i / CHAR_BIT] |= 1 << i % CHAR_BIT;
@@ -455,185 +690,208 @@ void unibi_set_bool(unibi_term *t, enum unibi_boolean v, int x) {
455 690
456 691 short unibi_get_num(const unibi_term *t, enum unibi_numeric v) {
457 692 size_t i;
458   - assert(v > unibi_numeric_begin_ && v < unibi_numeric_end_);
459   - if (v <= unibi_numeric_begin_ || v >= unibi_numeric_end_) {
460   - return -2;
461   - }
  693 + ASSERT_RETURN(v > unibi_numeric_begin_ && v < unibi_numeric_end_, -2);
462 694 i = v - unibi_numeric_begin_ - 1;
463 695 return t->nums[i];
464 696 }
465 697
466 698 void unibi_set_num(unibi_term *t, enum unibi_numeric v, short x) {
467 699 size_t i;
468   - assert(v > unibi_numeric_begin_ && v < unibi_numeric_end_);
469   - if (v <= unibi_numeric_begin_ || v >= unibi_numeric_end_) {
470   - return;
471   - }
  700 + ASSERT_RETURN_(v > unibi_numeric_begin_ && v < unibi_numeric_end_);
472 701 i = v - unibi_numeric_begin_ - 1;
473 702 t->nums[i] = x;
474 703 }
475 704
476 705 const char *unibi_get_str(const unibi_term *t, enum unibi_string v) {
477 706 size_t i;
478   - assert(v > unibi_string_begin_ && v < unibi_string_end_);
479   - if (v <= unibi_string_begin_ || v >= unibi_string_end_) {
480   - return NULL;
481   - }
  707 + ASSERT_RETURN(v > unibi_string_begin_ && v < unibi_string_end_, NULL);
482 708 i = v - unibi_string_begin_ - 1;
483 709 return t->strs[i];
484 710 }
485 711
486 712 void unibi_set_str(unibi_term *t, enum unibi_string v, const char *x) {
487 713 size_t i;
488   - assert(v > unibi_string_begin_ && v < unibi_string_end_);
489   - if (v <= unibi_string_begin_ || v >= unibi_string_end_) {
490   - return;
491   - }
  714 + ASSERT_RETURN_(v > unibi_string_begin_ && v < unibi_string_end_);
492 715 i = v - unibi_string_begin_ - 1;
493 716 t->strs[i] = x;
494 717 }
495 718
496 719
497   -#if 0
498   -int unibi_get_ext_bool(const unibi_term *t, const char *k) {
499   - size_t i;
  720 +size_t unibi_count_ext_bool(const unibi_term *t) {
  721 + return t->ext_bools.used;
  722 +}
500 723
501   - for (i = 0; i < t->ext_bsize && t->ext_bools[i].name; ++i) {
502   - if (strcmp(t->ext_bools[i].name, k) == 0) {
503   - return 1;
504   - }
505   - }
  724 +size_t unibi_count_ext_num(const unibi_term *t) {
  725 + return t->ext_nums.used;
  726 +}
506 727
507   - return 0;
  728 +size_t unibi_count_ext_str(const unibi_term *t) {
  729 + return t->ext_strs.used;
508 730 }
509 731
510   -int unibi_set_ext_bool(unibi_term *t, const char *k, int v) {
511   - size_t i;
  732 +int unibi_get_ext_bool(const unibi_term *t, size_t i) {
  733 + ASSERT_RETURN(i < t->ext_bools.used, -1);
  734 + return t->ext_bools.data[i] ? 1 : 0;
  735 +}
512 736
513   - for (i = 0; i < t->ext_bsize && t->ext_bools[i].name; ++i) {
514   - if (strcmp(t->ext_bools[i].name, k) == 0) {
515   - if (!v) {
516   - size_t j;
517   - for (j = i + 1; j < t->ext_bsize && t->ext_bools[j].name; ++j)
518   - ;
519   - memmove(t->ext_bools + i, t->ext_bools + i + 1, j - (i + 1));
520   - t->ext_bools[j - 1].name = NULL;
521   - }
522   - return 0;
523   - }
524   - }
  737 +const char *unibi_get_ext_bool_name(const unibi_term *t, size_t i) {
  738 + ASSERT_EXT_NAMES(t);
  739 + ASSERT_RETURN(i < t->ext_bools.used, NULL);
  740 + return t->ext_names.data[i];
  741 +}
525 742
526   - if (!v) {
527   - return 0;
528   - }
  743 +short unibi_get_ext_num(const unibi_term *t, size_t i) {
  744 + ASSERT_RETURN(i < t->ext_nums.used, -2);
  745 + return t->ext_nums.data[i];
  746 +}
529 747
530   - if (i >= t->ext_bsize) {
531   - const size_t size = (t->ext_bsize + 1) * 3 / 2;
532   - void *p = realloc(t->ext_bools, sizeof *t->ext_bools * size);
533   - if (!p) {
534   - return -1;
535   - }
536   - t->ext_bools = p;
537   - t->ext_bools[t->ext_bsize].name = NULL;
538   - t->ext_bsize = size;
539   - }
  748 +const char *unibi_get_ext_num_name(const unibi_term *t, size_t i) {
  749 + ASSERT_EXT_NAMES(t);
  750 + ASSERT_RETURN(i < t->ext_nums.used, NULL);
  751 + return t->ext_names.data[t->ext_bools.used + i];
  752 +}
540 753
541   - t->ext_bools[i].name = k;
542   - if (i + 1 < t->ext_bsize) {
543   - t->ext_bools[i + 1].name = NULL;
544   - }
545   - return 0;
  754 +const char *unibi_get_ext_str(const unibi_term *t, size_t i) {
  755 + ASSERT_RETURN(i < t->ext_strs.used, NULL);
  756 + return t->ext_strs.data[i];
546 757 }
547 758
548   -short unibi_get_ext_num(const unibi_term *t, const char *k) {
549   - size_t i;
  759 +const char *unibi_get_ext_str_name(const unibi_term *t, size_t i) {
  760 + ASSERT_EXT_NAMES(t);
  761 + ASSERT_RETURN(i < t->ext_strs.used, NULL);
  762 + return t->ext_names.data[t->ext_bools.used + t->ext_nums.used + i];
  763 +}
550 764
551   - for (i = 0; i < t->ext_nsize && t->ext_nums[i].name; ++i) {
552   - if (strcmp(t->ext_nums[i].name, k) == 0) {
553   - return t->ext_nums[i].value;
554   - }
555   - }
  765 +void unibi_set_ext_bool(unibi_term *t, size_t i, int v) {
  766 + ASSERT_RETURN_(i < t->ext_bools.used);
  767 + t->ext_bools.data[i] = !!v;
  768 +}
556 769
557   - return -1;
  770 +void unibi_set_ext_bool_name(unibi_term *t, size_t i, const char *c) {
  771 + ASSERT_EXT_NAMES(t);
  772 + ASSERT_RETURN_(i < t->ext_bools.used);
  773 + t->ext_names.data[i] = c;
558 774 }
559 775
560   -int unibi_set_ext_num(unibi_term *t, const char *k, short v) {
561   - size_t i;
  776 +void unibi_set_ext_num(unibi_term *t, size_t i, short v) {
  777 + ASSERT_RETURN_(i < t->ext_nums.used);
  778 + t->ext_nums.data[i] = v;
  779 +}
562 780
563   - for (i = 0; i < t->ext_nsize && t->ext_nums[i].name; ++i) {
564   - if (strcmp(t->ext_nums[i].name, k) == 0) {
565   - t->ext_nums[i].value = v;
566   - return 0;
567   - }
568   - }
  781 +void unibi_set_ext_num_name(unibi_term *t, size_t i, const char *c) {
  782 + ASSERT_EXT_NAMES(t);
  783 + ASSERT_RETURN_(i < t->ext_nums.used);
  784 + t->ext_names.data[t->ext_bools.used + i] = c;
  785 +}
569 786
570   - if ((unsigned short)v > MAX15BITS) {
571   - return 0;
572   - }
  787 +void unibi_set_ext_str(unibi_term *t, size_t i, const char *v) {
  788 + ASSERT_RETURN_(i < t->ext_strs.used);
  789 + t->ext_strs.data[i] = v;
  790 +}
573 791
574   - {
575   - const size_t size = (t->ext_nsize + 1) * 3 / 2;
576   - void *p = realloc(t->ext_nums, sizeof *t->ext_nums * size);
577   - if (!p) {
578   - return -1;
579   - }
  792 +void unibi_set_ext_str_name(unibi_term *t, size_t i, const char *c) {
  793 + ASSERT_EXT_NAMES(t);
  794 + ASSERT_RETURN_(i < t->ext_strs.used);
  795 + t->ext_names.data[t->ext_bools.used + t->ext_nums.used + i] = c;
  796 +}
580 797
581   - t->ext_nums = p;
582   - t->ext_nums[t->ext_nsize].name = NULL;
583   - t->ext_nsize = size;
  798 +size_t unibi_add_ext_bool(unibi_term *t, const char *c, int v) {
  799 + size_t r;
  800 + ASSERT_EXT_NAMES(t);
  801 + if (
  802 + !DYNARR(bool, ensure_slot)(&t->ext_bools) ||
  803 + !DYNARR(str, ensure_slot)(&t->ext_names)
  804 + ) {
  805 + return SIZE_ERR;
584 806 }
585   -
586   - t->ext_nums[i].name = k;
587   - t->ext_nums[i].value = v;
588   - if (i + 1 < t->ext_nsize) {
589   - t->ext_nums[i + 1].name = NULL;
  807 + {
  808 + const char **const p = t->ext_names.data + t->ext_bools.used;
  809 + memmove(p + 1, p, (t->ext_names.used - t->ext_bools.used) * sizeof *t->ext_names.data);
  810 + *p = c;
  811 + t->ext_names.used++;
590 812 }
591   - return 0;
  813 + r = t->ext_bools.used++;
  814 + t->ext_bools.data[r] = !!v;
  815 + return r;
592 816 }
593 817
594   -const char *unibi_get_ext_str(const unibi_term *t, const char *k) {
595   - size_t i;
596   -
597   - for (i = 0; i < t->ext_ssize && t->ext_strs[i].name; ++i) {
598   - if (strcmp(t->ext_strs[i].name, k) == 0) {
599   - return t->ext_strs[i].value;
600   - }
  818 +size_t unibi_add_ext_num(unibi_term *t, const char *c, short v) {
  819 + size_t r;
  820 + ASSERT_EXT_NAMES(t);
  821 + if (
  822 + !DYNARR(num, ensure_slot)(&t->ext_nums) ||
  823 + !DYNARR(str, ensure_slot)(&t->ext_names)
  824 + ) {
  825 + return SIZE_ERR;
601 826 }
602   -
603   - return NULL;
  827 + {
  828 + const char **const p = t->ext_names.data + t->ext_bools.used + t->ext_nums.used;
  829 + memmove(p + 1, p, (t->ext_names.used - t->ext_bools.used - t->ext_nums.used) * sizeof *t->ext_names.data);
  830 + *p = c;
  831 + t->ext_names.used++;
  832 + }
  833 + r = t->ext_nums.used++;
  834 + t->ext_nums.data[r] = v;
  835 + return r;
604 836 }
605 837
606   -int unibi_set_ext_str(unibi_term *t, const char *k, const char *v) {
607   - size_t i;
  838 +size_t unibi_add_ext_str(unibi_term *t, const char *c, const char *v) {
  839 + size_t r;
  840 + ASSERT_EXT_NAMES(t);
  841 + if (
  842 + !DYNARR(str, ensure_slot)(&t->ext_strs) ||
  843 + !DYNARR(str, ensure_slot)(&t->ext_names)
  844 + ) {
  845 + return SIZE_ERR;
  846 + }
  847 + t->ext_names.data[t->ext_names.used++] = c;
  848 + r = t->ext_strs.used++;
  849 + t->ext_strs.data[r] = v;
  850 + return r;
  851 +}
608 852
609   - for (i = 0; i < t->ext_ssize && t->ext_strs[i].name; ++i) {
610   - if (strcmp(t->ext_strs[i].name, k) == 0) {
611   - t->ext_strs[i].value = v;
612   - return 0;
613   - }
  853 +void unibi_del_ext_bool(unibi_term *t, size_t i) {
  854 + ASSERT_EXT_NAMES(t);
  855 + ASSERT_RETURN_(i < t->ext_bools.used);
  856 + {
  857 + unsigned char *const p = t->ext_bools.data + i;
  858 + memmove(p, p + 1, (t->ext_bools.used - i - 1) * sizeof *t->ext_bools.data);
  859 + t->ext_bools.used--;
614 860 }
615   -
616   - if (!v) {
617   - return 0;
  861 + {
  862 + const char **const p = t->ext_names.data + i;
  863 + memmove(p, p + 1, (t->ext_names.used - i - 1) * sizeof *t->ext_names.data);
  864 + t->ext_names.used--;
618 865 }
  866 +}
619 867
  868 +void unibi_del_ext_num(unibi_term *t, size_t i) {
  869 + ASSERT_EXT_NAMES(t);
  870 + ASSERT_RETURN_(i < t->ext_nums.used);
620 871 {
621   - const size_t size = (t->ext_ssize + 1) * 3 / 2;
622   - void *p = realloc(t->ext_strs, sizeof *t->ext_strs * size);
623   - if (!p) {
624   - return -1;
625   - }
626   -
627   - t->ext_strs = p;
628   - t->ext_strs[t->ext_ssize].name = NULL;
629   - t->ext_ssize = size;
  872 + short *const p = t->ext_nums.data + i;
  873 + memmove(p, p + 1, (t->ext_nums.used - i - 1) * sizeof *t->ext_nums.data);
  874 + t->ext_nums.used--;
  875 + }
  876 + {
  877 + const char **const p = t->ext_names.data + t->ext_bools.used + i;
  878 + memmove(p, p + 1, (t->ext_names.used - i - 1) * sizeof *t->ext_names.data);
  879 + t->ext_names.used--;
630 880 }
  881 +}
631 882
632   - t->ext_strs[i].name = k;
633   - t->ext_strs[i].value = v;
634   - if (i + 1 < t->ext_ssize) {
635   - t->ext_strs[i + 1].name = NULL;
  883 +void unibi_del_ext_str(unibi_term *t, size_t i) {
  884 + ASSERT_EXT_NAMES(t);
  885 + ASSERT_RETURN_(i < t->ext_strs.used);
  886 + {
  887 + const char **const p = t->ext_strs.data + i;
  888 + memmove(p, p + 1, (t->ext_strs.used - i - 1) * sizeof *t->ext_strs.data);
  889 + t->ext_strs.used--;
  890 + }
  891 + {
  892 + const char **const p = t->ext_names.data + t->ext_bools.used + t->ext_nums.used + i;
  893 + memmove(p, p + 1, (t->ext_names.used - i - 1) * sizeof *t->ext_names.data);
  894 + t->ext_names.used--;
636 895 }
637   - return 0;
638 896 }
639   -#endif
  897 +
40 unibilium.h
... ... @@ -1,7 +1,7 @@
1 1 #ifndef GUARD_UNIBILIUM_H_
2 2 #define GUARD_UNIBILIUM_H_
3 3
4   -/* Copyright 2008, 2010, 2011 Lukas Mai.
  4 +/* Copyright 2008, 2010-2012 Lukas Mai.
5 5 *
6 6 * This library is under the GNU Lesser General Public License;
7 7 * see the file LGPLv3 for details.
@@ -544,17 +544,6 @@ void unibi_set_num(unibi_term *, enum unibi_numeric, short);
544 544 const char *unibi_get_str(const unibi_term *, enum unibi_string);
545 545 void unibi_set_str(unibi_term *, enum unibi_string, const char *);
546 546
547   -#if 0
548   -int unibi_get_ext_bool(const unibi_term *, const char *);
549   -int unibi_set_ext_bool(unibi_term *, const char *, int);
550   -
551   -short unibi_get_ext_num(const unibi_term *, const char *);
552   -int unibi_set_ext_num(unibi_term *, const char *, short);
553   -
554   -const char *unibi_get_ext_str(const unibi_term *, const char *);
555   -int unibi_set_ext_str(unibi_term *, const char *, const char *);
556   -#endif
557   -
558 547 unibi_term *unibi_from_fp(FILE *);
559 548 unibi_term *unibi_from_fd(int);
560 549 unibi_term *unibi_from_file(const char *);
@@ -570,4 +559,31 @@ const char *unibi_short_name_num(enum unibi_numeric);
570 559 const char *unibi_name_str(enum unibi_string);
571 560 const char *unibi_short_name_str(enum unibi_string);
572 561
  562 +
  563 +size_t unibi_count_ext_bool(const unibi_term *);
  564 +size_t unibi_count_ext_num(const unibi_term *);
  565 +size_t unibi_count_ext_str(const unibi_term *);
  566 +
  567 +int unibi_get_ext_bool(const unibi_term *, size_t);
  568 +const char *unibi_get_ext_bool_name(const unibi_term *, size_t);
  569 +short unibi_get_ext_num(const unibi_term *, size_t);
  570 +const char *unibi_get_ext_num_name(const unibi_term *, size_t);
  571 +const char *unibi_get_ext_str(const unibi_term *, size_t);
  572 +const char *unibi_get_ext_str_name(const unibi_term *, size_t);
  573 +
  574 +void unibi_set_ext_bool(unibi_term *, size_t, int);
  575 +void unibi_set_ext_bool_name(unibi_term *, size_t, const char *);
  576 +void unibi_set_ext_num(unibi_term *, size_t, short);
  577 +void unibi_set_ext_num_name(unibi_term *, size_t, const char *);
  578 +void unibi_set_ext_str(unibi_term *, size_t, const char *);
  579 +void unibi_set_ext_str_name(unibi_term *, size_t, const char *);
  580 +
  581 +size_t unibi_add_ext_bool(unibi_term *, const char *, int);
  582 +size_t unibi_add_ext_num(unibi_term *, const char *, short);
  583 +size_t unibi_add_ext_str(unibi_term *, const char *, const char *);
  584 +
  585 +void unibi_del_ext_bool(unibi_term *, size_t);
  586 +void unibi_del_ext_num(unibi_term *, size_t);
  587 +void unibi_del_ext_str(unibi_term *, size_t);
  588 +
573 589 #endif /* GUARD_UNIBILIUM_H_ */

0 comments on commit e11128d

Please sign in to comment.
Something went wrong with that request. Please try again.