Annotation of embedaddon/mpd/src/contrib/libpdel/structs/type/structs_type_array.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (c) 2001-2002 Packet Design, LLC.
! 4: * All rights reserved.
! 5: *
! 6: * Subject to the following obligations and disclaimer of warranty,
! 7: * use and redistribution of this software, in source or object code
! 8: * forms, with or without modifications are expressly permitted by
! 9: * Packet Design; provided, however, that:
! 10: *
! 11: * (i) Any and all reproductions of the source or object code
! 12: * must include the copyright notice above and the following
! 13: * disclaimer of warranties; and
! 14: * (ii) No rights are granted, in any manner or form, to use
! 15: * Packet Design trademarks, including the mark "PACKET DESIGN"
! 16: * on advertising, endorsements, or otherwise except as such
! 17: * appears in the above copyright notice or in the software.
! 18: *
! 19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
! 20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
! 21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
! 22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
! 23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
! 24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
! 25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
! 26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
! 27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
! 28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
! 29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
! 30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
! 31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
! 32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
! 33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
! 35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
! 36: * THE POSSIBILITY OF SUCH DAMAGE.
! 37: *
! 38: * Author: Archie Cobbs <archie@freebsd.org>
! 39: */
! 40:
! 41: #include <sys/types.h>
! 42: #include <sys/param.h>
! 43: #include <netinet/in.h>
! 44: #include <arpa/inet.h>
! 45:
! 46: #include <stdio.h>
! 47: #include <stdlib.h>
! 48: #include <stdarg.h>
! 49: #include <string.h>
! 50: #include <errno.h>
! 51:
! 52: #include "structs/structs.h"
! 53: #include "structs/type/array.h"
! 54: #include "util/typed_mem.h"
! 55:
! 56: #define NUM_BYTES(x) (((x) + 7) / 8)
! 57:
! 58: /*********************************************************************
! 59: ARRAY TYPES
! 60: *********************************************************************/
! 61:
! 62: int
! 63: structs_array_copy(const struct structs_type *type,
! 64: const void *from, void *to)
! 65: {
! 66: const struct structs_type *const etype = type->args[0].v;
! 67: const char *mtype = type->args[1].v;
! 68: const struct structs_array *const fary = from;
! 69: struct structs_array *const tary = to;
! 70: int errno_save;
! 71: u_int i;
! 72:
! 73: /* Make sure it's really an array type */
! 74: if (type->tclass != STRUCTS_TYPE_ARRAY) {
! 75: errno = EINVAL;
! 76: return (-1);
! 77: }
! 78:
! 79: /* Allocate a new array */
! 80: memset(tary, 0, sizeof(*tary));
! 81: if ((tary->elems = MALLOC(mtype,
! 82: fary->length * etype->size)) == NULL)
! 83: return (-1);
! 84:
! 85: /* Copy elements into it */
! 86: for (i = 0; i < fary->length; i++) {
! 87: const void *const from_elem
! 88: = (char *)fary->elems + (i * etype->size);
! 89: void *const to_elem = (char *)tary->elems + (i * etype->size);
! 90:
! 91: if ((*etype->copy)(etype, from_elem, to_elem) == -1)
! 92: break;
! 93: tary->length++;
! 94: }
! 95:
! 96: /* If there was a failure, undo the half completed job */
! 97: if (i < fary->length) {
! 98: errno_save = errno;
! 99: while (i-- > 0) {
! 100: (*etype->uninit)(etype,
! 101: (char *)tary->elems + (i * etype->size));
! 102: }
! 103: FREE(mtype, tary->elems);
! 104: memset(tary, 0, sizeof(*tary));
! 105: errno = errno_save;
! 106: return (-1);
! 107: }
! 108:
! 109: /* Done */
! 110: return (0);
! 111: }
! 112:
! 113: int
! 114: structs_array_equal(const struct structs_type *type,
! 115: const void *v1, const void *v2)
! 116: {
! 117: const struct structs_type *const etype = type->args[0].v;
! 118: const struct structs_array *const ary1 = v1;
! 119: const struct structs_array *const ary2 = v2;
! 120: u_int i;
! 121:
! 122: /* Make sure it's really an array type */
! 123: if (type->tclass != STRUCTS_TYPE_ARRAY)
! 124: return (0);
! 125:
! 126: /* Check array lengths first */
! 127: if (ary1->length != ary2->length)
! 128: return (0);
! 129:
! 130: /* Now compare individual elements */
! 131: for (i = 0;
! 132: i < ary1->length && (*etype->equal)(etype,
! 133: (char *)ary1->elems + (i * etype->size),
! 134: (char *)ary2->elems + (i * etype->size));
! 135: i++);
! 136: return (i == ary1->length);
! 137: }
! 138:
! 139: int
! 140: structs_array_encode(const struct structs_type *type, const char *mtype,
! 141: struct structs_data *code, const void *data)
! 142: {
! 143: const struct structs_type *const etype = type->args[0].v;
! 144: const struct structs_array *const ary = data;
! 145: const u_int bitslen = NUM_BYTES(ary->length);
! 146: struct structs_data *ecodes;
! 147: u_int32_t elength;
! 148: u_char *bits;
! 149: void *delem;
! 150: u_int tlen;
! 151: int r = -1;
! 152: u_int i;
! 153:
! 154: /* Make sure it's really an array type */
! 155: if (type->tclass != STRUCTS_TYPE_ARRAY) {
! 156: errno = EINVAL;
! 157: return (-1);
! 158: }
! 159:
! 160: /* Get the default value for an element */
! 161: if ((delem = MALLOC(TYPED_MEM_TEMP, etype->size)) == NULL)
! 162: return (-1);
! 163: if (structs_init(etype, NULL, delem) == -1)
! 164: goto fail1;
! 165:
! 166: /* Create bit array. Each bit indicates an element that is present. */
! 167: if ((bits = MALLOC(TYPED_MEM_TEMP, bitslen)) == NULL)
! 168: goto fail2;
! 169: memset(bits, 0, bitslen);
! 170: tlen = 4 + bitslen; /* length word + bits array */
! 171:
! 172: /* Create array of individual encodings, one per element */
! 173: if ((ecodes = MALLOC(TYPED_MEM_TEMP,
! 174: ary->length * sizeof(*ecodes))) == NULL)
! 175: goto fail3;
! 176: for (i = 0; i < ary->length; i++) {
! 177: const void *const elem = (char *)ary->elems + (i * etype->size);
! 178: struct structs_data *const ecode = &ecodes[i];
! 179:
! 180: /* Check for default value, leave out if same as */
! 181: if ((*etype->equal)(etype, elem, delem) == 1) {
! 182: memset(ecode, 0, sizeof(*ecode));
! 183: continue;
! 184: }
! 185: bits[i / 8] |= (1 << (i % 8));
! 186:
! 187: /* Encode element */
! 188: if ((*etype->encode)(etype, TYPED_MEM_TEMP, ecode, elem) == -1)
! 189: goto fail4;
! 190: tlen += ecode->length;
! 191: }
! 192:
! 193: /* Allocate final encoded region */
! 194: if ((code->data = MALLOC(mtype, tlen)) == NULL)
! 195: goto fail4;
! 196:
! 197: /* Copy array length */
! 198: elength = htonl(ary->length);
! 199: memcpy(code->data, &elength, 4);
! 200: code->length = 4;
! 201:
! 202: /* Copy bits array */
! 203: memcpy(code->data + code->length, bits, bitslen);
! 204: code->length += bitslen;
! 205:
! 206: /* Copy encoded elements */
! 207: for (i = 0; i < ary->length; i++) {
! 208: struct structs_data *const ecode = &ecodes[i];
! 209:
! 210: memcpy(code->data + code->length, ecode->data, ecode->length);
! 211: code->length += ecode->length;
! 212: }
! 213:
! 214: /* OK */
! 215: r = 0;
! 216:
! 217: /* Clean up and exit */
! 218: fail4: while (i-- > 0)
! 219: FREE(TYPED_MEM_TEMP, ecodes[i].data);
! 220: FREE(TYPED_MEM_TEMP, ecodes);
! 221: fail3: FREE(TYPED_MEM_TEMP, bits);
! 222: fail2: structs_free(etype, NULL, delem);
! 223: fail1: FREE(TYPED_MEM_TEMP, delem);
! 224: return (r);
! 225: }
! 226:
! 227: int
! 228: structs_array_decode(const struct structs_type *type, const u_char *code,
! 229: size_t cmax, void *data, char *ebuf, size_t emax)
! 230: {
! 231: const struct structs_type *const etype = type->args[0].v;
! 232: const char *const mtype = type->args[1].v;
! 233: struct structs_array *const ary = data;
! 234: const u_char *bits;
! 235: u_int32_t elength;
! 236: u_int bitslen;
! 237: int clen;
! 238: u_int i;
! 239:
! 240: /* Make sure it's really an array type */
! 241: if (type->tclass != STRUCTS_TYPE_ARRAY) {
! 242: errno = EINVAL;
! 243: return (-1);
! 244: }
! 245:
! 246: /* Get number of elements */
! 247: if (cmax < 4)
! 248: goto truncated;
! 249: memcpy(&elength, code, 4);
! 250: ary->length = ntohl(elength);
! 251: code += 4;
! 252: cmax -= 4;
! 253: clen = 4;
! 254:
! 255: /* Get bits array */
! 256: bitslen = NUM_BYTES(ary->length);
! 257: if (cmax < bitslen) {
! 258: truncated: strlcpy(ebuf, "encoded array is truncated", emax);
! 259: errno = EINVAL;
! 260: return (-1);
! 261: }
! 262: bits = code;
! 263: code += bitslen;
! 264: cmax -= bitslen;
! 265: clen += bitslen;
! 266:
! 267: /* Allocate array elements */
! 268: if ((ary->elems = MALLOC(mtype, ary->length * etype->size)) == NULL)
! 269: return (-1);
! 270:
! 271: /* Decode elements */
! 272: for (i = 0; i < ary->length; i++) {
! 273: void *const edata = (char *)ary->elems + (i * etype->size);
! 274: int eclen;
! 275:
! 276: /* If element not present, assign it the default value */
! 277: if ((bits[i / 8] & (1 << (i % 8))) == 0) {
! 278: if (structs_init(etype, NULL, edata) == -1)
! 279: goto fail;
! 280: continue;
! 281: }
! 282:
! 283: /* Decode element */
! 284: if ((eclen = (*etype->decode)(etype,
! 285: code, cmax, edata, ebuf, emax)) == -1)
! 286: goto fail;
! 287:
! 288: /* Go to next encoded element */
! 289: code += eclen;
! 290: cmax -= eclen;
! 291: clen += eclen;
! 292: continue;
! 293:
! 294: /* Un-do work done so far */
! 295: fail: while (i-- > 0) {
! 296: structs_free(etype, NULL,
! 297: (char *)ary->elems + (i * etype->size));
! 298: }
! 299: FREE(mtype, ary->elems);
! 300: return (-1);
! 301: }
! 302:
! 303: /* Done */
! 304: return (clen);
! 305: }
! 306:
! 307: void
! 308: structs_array_free(const struct structs_type *type, void *data)
! 309: {
! 310: const struct structs_type *const etype = type->args[0].v;
! 311: const char *mtype = type->args[1].v;
! 312: struct structs_array *const ary = data;
! 313: u_int i;
! 314:
! 315: /* Make sure it's really an array type */
! 316: if (type->tclass != STRUCTS_TYPE_ARRAY)
! 317: return;
! 318:
! 319: /* Free individual elements */
! 320: for (i = 0; i < ary->length; i++)
! 321: (*etype->uninit)(etype, (char *)ary->elems + (i * etype->size));
! 322:
! 323: /* Free array itself */
! 324: FREE(mtype, ary->elems);
! 325: memset(ary, 0, sizeof(*ary));
! 326: }
! 327:
! 328: int
! 329: structs_array_length(const struct structs_type *type,
! 330: const char *name, const void *data)
! 331: {
! 332: const struct structs_array *ary = data;
! 333:
! 334: /* Find array */
! 335: if ((type = structs_find(type, name, (void **)&ary, 0)) == NULL)
! 336: return (-1);
! 337:
! 338: /* Make sure it's really an array type */
! 339: if (type->tclass != STRUCTS_TYPE_ARRAY) {
! 340: errno = EINVAL;
! 341: return (-1);
! 342: }
! 343:
! 344: /* Return length */
! 345: return (ary->length);
! 346: }
! 347:
! 348: int
! 349: structs_array_reset(const struct structs_type *type,
! 350: const char *name, void *data)
! 351: {
! 352: /* Find array */
! 353: if ((type = structs_find(type, name, &data, 1)) == NULL)
! 354: return (-1);
! 355:
! 356: /* Make sure it's really an array type */
! 357: if (type->tclass != STRUCTS_TYPE_ARRAY) {
! 358: errno = EINVAL;
! 359: return (-1);
! 360: }
! 361:
! 362: /* Free it, which resets it as well */
! 363: structs_array_free(type, data);
! 364: return (0);
! 365: }
! 366:
! 367: int
! 368: structs_array_insert(const struct structs_type *type,
! 369: const char *name, u_int index, void *data)
! 370: {
! 371: struct structs_array *ary = data;
! 372: const struct structs_type *etype;
! 373: const char *mtype;
! 374: void *mem;
! 375:
! 376: /* Find array */
! 377: if ((type = structs_find(type, name, (void **)&ary, 0)) == NULL)
! 378: return (-1);
! 379: etype = type->args[0].v;
! 380: mtype = type->args[1].v;
! 381:
! 382: /* Make sure it's really an array type */
! 383: if (type->tclass != STRUCTS_TYPE_ARRAY) {
! 384: errno = EINVAL;
! 385: return (-1);
! 386: }
! 387:
! 388: /* Check index */
! 389: if (index > ary->length) {
! 390: errno = EDOM;
! 391: return (-1);
! 392: }
! 393:
! 394: /* Reallocate array, leaving room for new element and a shift */
! 395: if ((mem = REALLOC(mtype,
! 396: ary->elems, (ary->length + 2) * etype->size)) == NULL)
! 397: return (-1);
! 398: ary->elems = mem;
! 399:
! 400: /* Initialize new element; we'll move it into place later */
! 401: if ((*etype->init)(etype,
! 402: (char *)ary->elems + (ary->length + 1) * etype->size) == -1)
! 403: return (-1);
! 404:
! 405: /* Shift array over by one and move new element into place */
! 406: memmove((char *)ary->elems + (index + 1) * etype->size,
! 407: (char *)ary->elems + index * etype->size,
! 408: (ary->length - index) * etype->size);
! 409: memcpy((char *)ary->elems + index * etype->size,
! 410: (char *)ary->elems + (ary->length + 1) * etype->size, etype->size);
! 411: ary->length++;
! 412: return (0);
! 413: }
! 414:
! 415: int
! 416: structs_array_delete(const struct structs_type *type,
! 417: const char *name, u_int index, void *data)
! 418: {
! 419: const struct structs_type *etype;
! 420: struct structs_array *ary = data;
! 421:
! 422: /* Find array */
! 423: if ((type = structs_find(type, name, (void **)&ary, 0)) == NULL)
! 424: return (-1);
! 425: etype = type->args[0].v;
! 426:
! 427: /* Make sure it's really an array type */
! 428: if (type->tclass != STRUCTS_TYPE_ARRAY) {
! 429: errno = EINVAL;
! 430: return (-1);
! 431: }
! 432:
! 433: /* Check index */
! 434: if (index >= ary->length) {
! 435: errno = EDOM;
! 436: return (-1);
! 437: }
! 438:
! 439: /* Free element */
! 440: (*etype->uninit)(etype, (char *)ary->elems + (index * etype->size));
! 441:
! 442: /* Shift array */
! 443: memmove((char *)ary->elems + index * etype->size,
! 444: (char *)ary->elems + (index + 1) * etype->size,
! 445: (--ary->length - index) * etype->size);
! 446: return (0);
! 447: }
! 448:
! 449: /*
! 450: * Given a name, prepare all arrays in the name path for being
! 451: * set with a new element.
! 452: *
! 453: * This means that any array index equal to the length of the array
! 454: * causes a new element to be appended to the array rather than
! 455: * an element not found error, and that any array index equal to
! 456: * zero means to reset the entire array to be empty.
! 457: *
! 458: * This allows an entire array to be set by setting each element
! 459: * in order, as long as this function is called with the name of
! 460: * the element before each set operation.
! 461: */
! 462: int
! 463: structs_array_prep(const struct structs_type *type,
! 464: const char *name, void *data)
! 465: {
! 466: char *nbuf;
! 467: char *s;
! 468:
! 469: /* Skip if name cannot be an array element name */
! 470: if (name == NULL || *name == '\0')
! 471: return (0);
! 472:
! 473: /* Copy name into writable buffer */
! 474: if ((nbuf = MALLOC(TYPED_MEM_TEMP, strlen(name) + 2)) == NULL)
! 475: return (-1);
! 476: nbuf[0] = '*'; /* for debugging */
! 477: strcpy(nbuf + 1, name);
! 478:
! 479: /* Check all array element names in name path */
! 480: for (s = nbuf; s != NULL; s = strchr(s + 1, STRUCTS_SEPARATOR)) {
! 481: const struct structs_type *atype;
! 482: struct structs_array *ary = data;
! 483: u_long index;
! 484: char *eptr;
! 485: char *t;
! 486: char ch;
! 487:
! 488: /* Go to next descendant node using prefix of name */
! 489: ch = *s;
! 490: *s = '\0';
! 491: if ((atype = structs_find(type,
! 492: nbuf + (s != nbuf), (void **)&ary, 1)) == NULL) {
! 493: FREE(TYPED_MEM_TEMP, nbuf);
! 494: return (-1);
! 495: }
! 496: *s = ch;
! 497:
! 498: /* If not array type, continue */
! 499: if (atype->tclass != STRUCTS_TYPE_ARRAY)
! 500: continue;
! 501:
! 502: /* Get array index */
! 503: if ((t = strchr(s + 1, STRUCTS_SEPARATOR)) != NULL)
! 504: *t = '\0';
! 505: index = strtoul(s + 1, &eptr, 10);
! 506: if (eptr == s + 1 || *eptr != '\0') {
! 507: errno = ENOENT;
! 508: FREE(TYPED_MEM_TEMP, nbuf);
! 509: return (-1);
! 510: }
! 511:
! 512: /* If setting an element that already exists, accept */
! 513: if (index < ary->length)
! 514: goto next;
! 515:
! 516: /* Must be setting the next new item in the array */
! 517: if (index != ary->length) {
! 518: errno = ENOENT;
! 519: FREE(TYPED_MEM_TEMP, nbuf);
! 520: return (-1);
! 521: }
! 522:
! 523: /* Add new item; it will be in an initialized state */
! 524: if (structs_array_insert(atype, NULL, ary->length, ary) == -1) {
! 525: FREE(TYPED_MEM_TEMP, nbuf);
! 526: return (-1);
! 527: }
! 528:
! 529: next:
! 530: /* Repair name buffer for next time */
! 531: if (t != NULL)
! 532: *t = STRUCTS_SEPARATOR;
! 533: }
! 534:
! 535: /* Done */
! 536: FREE(TYPED_MEM_TEMP, nbuf);
! 537: return (0);
! 538: }
! 539:
! 540: /*********************************************************************
! 541: FIXEDARRAY TYPES
! 542: *********************************************************************/
! 543:
! 544: int
! 545: structs_fixedarray_init(const struct structs_type *type, void *data)
! 546: {
! 547: const struct structs_type *const etype = type->args[0].v;
! 548: const u_int length = type->args[2].i;
! 549: u_int i;
! 550:
! 551: for (i = 0; i < length; i++) {
! 552: if ((*etype->init)(etype,
! 553: (char *)data + (i * etype->size)) == -1) {
! 554: while (i-- > 0) {
! 555: (*etype->uninit)(etype,
! 556: (char *)data + (i * etype->size));
! 557: }
! 558: return (-1);
! 559: }
! 560: }
! 561: return (0);
! 562: }
! 563:
! 564: int
! 565: structs_fixedarray_copy(const struct structs_type *type,
! 566: const void *from, void *to)
! 567: {
! 568: const struct structs_type *const etype = type->args[0].v;
! 569: const u_int length = type->args[2].i;
! 570: u_int i;
! 571:
! 572: /* Make sure it's really a fixedarray type */
! 573: if (type->tclass != STRUCTS_TYPE_FIXEDARRAY) {
! 574: errno = EINVAL;
! 575: return (-1);
! 576: }
! 577:
! 578: /* Copy elements into it */
! 579: for (i = 0; i < length; i++) {
! 580: const void *const from_elem = (char *)from + (i * etype->size);
! 581: void *const to_elem = (char *)to + (i * etype->size);
! 582:
! 583: if ((*etype->copy)(etype, from_elem, to_elem) == -1)
! 584: break;
! 585: }
! 586:
! 587: /* If there was a failure, undo the half completed job */
! 588: if (i < length) {
! 589: while (i-- > 0)
! 590: (*etype->uninit)(etype, (char *)to + (i * etype->size));
! 591: return (-1);
! 592: }
! 593:
! 594: /* Done */
! 595: return (0);
! 596: }
! 597:
! 598: int
! 599: structs_fixedarray_equal(const struct structs_type *type,
! 600: const void *v1, const void *v2)
! 601: {
! 602: const struct structs_type *const etype = type->args[0].v;
! 603: const u_int length = type->args[2].i;
! 604: u_int i;
! 605:
! 606: /* Make sure it's really a fixedarray type */
! 607: if (type->tclass != STRUCTS_TYPE_FIXEDARRAY)
! 608: return (0);
! 609:
! 610: /* Compare individual elements */
! 611: for (i = 0;
! 612: i < length && (*etype->equal)(etype,
! 613: (char *)v1 + (i * etype->size), (char *)v2 + (i * etype->size));
! 614: i++);
! 615: return (i == length);
! 616: }
! 617:
! 618: int
! 619: structs_fixedarray_encode(const struct structs_type *type, const char *mtype,
! 620: struct structs_data *code, const void *data)
! 621: {
! 622: const struct structs_type *const etype = type->args[0].v;
! 623: const u_int length = type->args[2].i;
! 624: const u_int bitslen = NUM_BYTES(length);
! 625: struct structs_data *ecodes;
! 626: u_char *bits;
! 627: void *delem;
! 628: u_int tlen;
! 629: int r = -1;
! 630: u_int i;
! 631:
! 632: /* Make sure it's really a fixedarray type */
! 633: if (type->tclass != STRUCTS_TYPE_FIXEDARRAY) {
! 634: errno = EINVAL;
! 635: return (-1);
! 636: }
! 637:
! 638: /* Get the default value for an element */
! 639: if ((delem = MALLOC(TYPED_MEM_TEMP, etype->size)) == NULL)
! 640: return (-1);
! 641: if (structs_init(etype, NULL, delem) == -1)
! 642: goto fail1;
! 643:
! 644: /* Create bit array. Each bit indicates an element that is present. */
! 645: if ((bits = MALLOC(TYPED_MEM_TEMP, bitslen)) == NULL)
! 646: goto fail2;
! 647: memset(bits, 0, bitslen);
! 648: tlen = bitslen;
! 649:
! 650: /* Create array of individual encodings, one per element */
! 651: if ((ecodes = MALLOC(TYPED_MEM_TEMP, length * sizeof(*ecodes))) == NULL)
! 652: goto fail3;
! 653: for (i = 0; i < length; i++) {
! 654: const void *const elem = (char *)data + (i * etype->size);
! 655: struct structs_data *const ecode = &ecodes[i];
! 656:
! 657: /* Check for default value, leave out if same as */
! 658: if ((*etype->equal)(etype, elem, delem) == 1) {
! 659: memset(ecode, 0, sizeof(*ecode));
! 660: continue;
! 661: }
! 662: bits[i / 8] |= (1 << (i % 8));
! 663:
! 664: /* Encode element */
! 665: if ((*etype->encode)(etype, TYPED_MEM_TEMP, ecode, elem) == -1)
! 666: goto fail4;
! 667: tlen += ecode->length;
! 668: }
! 669:
! 670: /* Allocate final encoded region */
! 671: if ((code->data = MALLOC(mtype, tlen)) == NULL)
! 672: goto fail4;
! 673:
! 674: /* Copy bits array */
! 675: memcpy(code->data, bits, bitslen);
! 676: code->length = bitslen;
! 677:
! 678: /* Copy encoded elements */
! 679: for (i = 0; i < length; i++) {
! 680: struct structs_data *const ecode = &ecodes[i];
! 681:
! 682: memcpy(code->data + code->length, ecode->data, ecode->length);
! 683: code->length += ecode->length;
! 684: }
! 685:
! 686: /* OK */
! 687: r = 0;
! 688:
! 689: /* Clean up and exit */
! 690: fail4: while (i-- > 0)
! 691: FREE(TYPED_MEM_TEMP, ecodes[i].data);
! 692: FREE(TYPED_MEM_TEMP, ecodes);
! 693: fail3: FREE(TYPED_MEM_TEMP, bits);
! 694: fail2: structs_free(etype, NULL, delem);
! 695: fail1: FREE(TYPED_MEM_TEMP, delem);
! 696: return (r);
! 697: }
! 698:
! 699: int
! 700: structs_fixedarray_decode(const struct structs_type *type, const u_char *code,
! 701: size_t cmax, void *data, char *ebuf, size_t emax)
! 702: {
! 703: const struct structs_type *const etype = type->args[0].v;
! 704: const u_int length = type->args[2].i;
! 705: const u_int bitslen = NUM_BYTES(length);
! 706: const u_char *bits;
! 707: int clen = 0;
! 708: u_int i;
! 709:
! 710: /* Make sure it's really a fixedarray type */
! 711: if (type->tclass != STRUCTS_TYPE_FIXEDARRAY) {
! 712: errno = EINVAL;
! 713: return (-1);
! 714: }
! 715:
! 716: /* Get bits array */
! 717: if (cmax < bitslen) {
! 718: strlcpy(ebuf, "encoded array is truncated", emax);
! 719: errno = EINVAL;
! 720: return (-1);
! 721: }
! 722: bits = code;
! 723: code += bitslen;
! 724: cmax -= bitslen;
! 725: clen += bitslen;
! 726:
! 727: /* Decode elements */
! 728: for (i = 0; i < length; i++) {
! 729: void *const edata = (char *)data + (i * etype->size);
! 730: int eclen;
! 731:
! 732: /* If element not present, assign it the default value */
! 733: if ((bits[i / 8] & (1 << (i % 8))) == 0) {
! 734: if (structs_init(etype, NULL, edata) == -1)
! 735: goto fail;
! 736: continue;
! 737: }
! 738:
! 739: /* Decode element */
! 740: if ((eclen = (*etype->decode)(etype,
! 741: code, cmax, edata, ebuf, emax)) == -1)
! 742: goto fail;
! 743:
! 744: /* Go to next encoded element */
! 745: code += eclen;
! 746: cmax -= eclen;
! 747: clen += eclen;
! 748: continue;
! 749:
! 750: /* Un-do work done so far */
! 751: fail: while (i-- > 0) {
! 752: structs_free(etype, NULL,
! 753: (char *)data + (i * etype->size));
! 754: }
! 755: return (-1);
! 756: }
! 757:
! 758: /* Done */
! 759: return (clen);
! 760: }
! 761:
! 762: void
! 763: structs_fixedarray_free(const struct structs_type *type, void *data)
! 764: {
! 765: const struct structs_type *const etype = type->args[0].v;
! 766: const u_int length = type->args[2].i;
! 767: u_int i;
! 768:
! 769: /* Make sure it's really a fixedarray type */
! 770: if (type->tclass != STRUCTS_TYPE_FIXEDARRAY)
! 771: return;
! 772:
! 773: /* Free elements */
! 774: for (i = 0; i < length; i++)
! 775: (*etype->uninit)(etype, (char *)data + (i * etype->size));
! 776: }
! 777:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>