Annotation of embedaddon/mpd/src/contrib/libpdel/structs/type/structs_type_array.c, revision 1.1.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>