Annotation of embedaddon/mpd/src/contrib/libpdel/structs/type/structs_type_struct.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:
! 43: #include <stdio.h>
! 44: #include <stdlib.h>
! 45: #include <stdarg.h>
! 46: #include <string.h>
! 47: #include <assert.h>
! 48: #include <errno.h>
! 49:
! 50: #include "structs/structs.h"
! 51: #include "structs/type/array.h"
! 52: #include "structs/type/struct.h"
! 53: #include "util/typed_mem.h"
! 54:
! 55: #define NUM_BYTES(x) (((x) + 7) / 8)
! 56:
! 57: /*********************************************************************
! 58: STRUCTURE TYPES
! 59: *********************************************************************/
! 60:
! 61: int
! 62: structs_struct_init(const struct structs_type *type, void *data)
! 63: {
! 64: const struct structs_field *field;
! 65:
! 66: /* Make sure it's really a structure type */
! 67: if (type->tclass != STRUCTS_TYPE_STRUCTURE) {
! 68: errno = EINVAL;
! 69: return (-1);
! 70: }
! 71:
! 72: /* Initialize each field */
! 73: memset(data, 0, type->size);
! 74: for (field = type->args[0].v; field->name != NULL; field++) {
! 75: assert(field->size == field->type->size); /* safety check */
! 76: if ((*field->type->init)(field->type,
! 77: (char *)data + field->offset) == -1)
! 78: break;
! 79: }
! 80:
! 81: /* If there was a failure, clean up */
! 82: if (field->name != NULL) {
! 83: while (field-- != type->args[0].v) {
! 84: (*field->type->uninit)(field->type,
! 85: (char *)data + field->offset);
! 86: }
! 87: memset((char *)data, 0, type->size);
! 88: return (-1);
! 89: }
! 90: return (0);
! 91: }
! 92:
! 93: int
! 94: structs_struct_copy(const struct structs_type *type,
! 95: const void *from, void *to)
! 96: {
! 97: const struct structs_field *field;
! 98:
! 99: /* Make sure it's really a structure type */
! 100: if (type->tclass != STRUCTS_TYPE_STRUCTURE) {
! 101: errno = EINVAL;
! 102: return (-1);
! 103: }
! 104:
! 105: /* Copy each field */
! 106: memset(to, 0, type->size);
! 107: for (field = type->args[0].v; field->name != NULL; field++) {
! 108: const void *const fdata = (char *)from + field->offset;
! 109: void *const tdata = (char *)to + field->offset;
! 110:
! 111: if ((*field->type->copy)(field->type, fdata, tdata) == -1)
! 112: break;
! 113: }
! 114:
! 115: /* If there was a failure, clean up */
! 116: if (field->name != NULL) {
! 117: while (field-- != type->args[0].v) {
! 118: (*field->type->uninit)(field->type,
! 119: (char *)to + field->offset);
! 120: }
! 121: memset((char *)to, 0, type->size);
! 122: }
! 123: return (0);
! 124: }
! 125:
! 126: int
! 127: structs_struct_equal(const struct structs_type *type,
! 128: const void *v1, const void *v2)
! 129: {
! 130: const struct structs_field *field;
! 131:
! 132: /* Make sure it's really a structure type */
! 133: if (type->tclass != STRUCTS_TYPE_STRUCTURE)
! 134: return (0);
! 135:
! 136: /* Compare all fields */
! 137: for (field = type->args[0].v; field->name != NULL; field++) {
! 138: const void *const data1 = (char *)v1 + field->offset;
! 139: const void *const data2 = (char *)v2 + field->offset;
! 140:
! 141: if (!(*field->type->equal)(field->type, data1, data2))
! 142: return (0);
! 143: }
! 144: return (1);
! 145: }
! 146:
! 147: int
! 148: structs_struct_encode(const struct structs_type *type, const char *mtype,
! 149: struct structs_data *code, const void *data)
! 150: {
! 151: struct structs_data *fcodes;
! 152: u_int nfields;
! 153: u_int bitslen;
! 154: u_char *bits;
! 155: int r = -1;
! 156: u_int tlen;
! 157: u_int i;
! 158:
! 159: /* Count number of fields */
! 160: for (nfields = 0;
! 161: ((struct structs_field *)type->args[0].v)[nfields].name != NULL;
! 162: nfields++);
! 163:
! 164: /* Create bit array. Each bit indicates a field as being present. */
! 165: bitslen = NUM_BYTES(nfields);
! 166: if ((bits = MALLOC(TYPED_MEM_TEMP, bitslen)) == NULL)
! 167: return (-1);
! 168: memset(bits, 0, bitslen);
! 169: tlen = bitslen;
! 170:
! 171: /* Create array of individual encodings, one per field */
! 172: if ((fcodes = MALLOC(TYPED_MEM_TEMP,
! 173: nfields * sizeof(*fcodes))) == NULL)
! 174: goto fail1;
! 175: for (i = 0; i < nfields; i++) {
! 176: const struct structs_field *const field
! 177: = (struct structs_field *)type->args[0].v + i;
! 178: const void *const fdata = (char *)data + field->offset;
! 179: struct structs_data *const fcode = &fcodes[i];
! 180: void *dval;
! 181: int equal;
! 182:
! 183: /* Compare this field to the default value */
! 184: if ((dval = MALLOC(TYPED_MEM_TEMP, field->type->size)) == NULL)
! 185: goto fail2;
! 186: if (structs_init(field->type, NULL, dval) == -1) {
! 187: FREE(TYPED_MEM_TEMP, dval);
! 188: goto fail2;
! 189: }
! 190: equal = (*field->type->equal)(field->type, fdata, dval);
! 191: structs_free(field->type, NULL, dval);
! 192: FREE(TYPED_MEM_TEMP, dval);
! 193:
! 194: /* Omit field if value equals default value */
! 195: if (equal == 1) {
! 196: memset(fcode, 0, sizeof(*fcode));
! 197: continue;
! 198: }
! 199: bits[i / 8] |= (1 << (i % 8));
! 200:
! 201: /* Encode this field */
! 202: if ((*field->type->encode)(field->type, TYPED_MEM_TEMP,
! 203: fcode, (char *)data + field->offset) == -1)
! 204: goto fail2;
! 205: tlen += fcode->length;
! 206: }
! 207:
! 208: /* Allocate final encoded region */
! 209: if ((code->data = MALLOC(mtype, tlen)) == NULL)
! 210: goto done;
! 211:
! 212: /* Copy bits */
! 213: memcpy(code->data, bits, bitslen);
! 214: code->length = bitslen;
! 215:
! 216: /* Copy encoded fields */
! 217: for (i = 0; i < nfields; i++) {
! 218: struct structs_data *const fcode = &fcodes[i];
! 219:
! 220: memcpy(code->data + code->length, fcode->data, fcode->length);
! 221: code->length += fcode->length;
! 222: }
! 223:
! 224: /* OK */
! 225: r = 0;
! 226:
! 227: done:
! 228: /* Clean up and exit */
! 229: fail2: while (i-- > 0)
! 230: FREE(TYPED_MEM_TEMP, fcodes[i].data);
! 231: FREE(TYPED_MEM_TEMP, fcodes);
! 232: fail1: FREE(TYPED_MEM_TEMP, bits);
! 233: return (r);
! 234: }
! 235:
! 236: int
! 237: structs_struct_decode(const struct structs_type *type, const u_char *code,
! 238: size_t cmax, void *data, char *ebuf, size_t emax)
! 239: {
! 240: const u_char *bits;
! 241: u_int nfields;
! 242: u_int bitslen;
! 243: u_int clen;
! 244: u_int i;
! 245:
! 246: /* Count number of fields */
! 247: for (nfields = 0;
! 248: ((struct structs_field *)type->args[0].v)[nfields].name != NULL;
! 249: nfields++);
! 250:
! 251: /* Get bits array */
! 252: bitslen = NUM_BYTES(nfields);
! 253: if (cmax < bitslen) {
! 254: strlcpy(ebuf, "encoded structure is truncated", emax);
! 255: errno = EINVAL;
! 256: return (-1);
! 257: }
! 258: bits = code;
! 259: code += bitslen;
! 260: cmax -= bitslen;
! 261: clen = bitslen;
! 262:
! 263: /* Decode fields */
! 264: for (i = 0; i < nfields; i++) {
! 265: const struct structs_field *const field
! 266: = (struct structs_field *)type->args[0].v + i;
! 267: void *const fdata = (char *)data + field->offset;
! 268: int fclen;
! 269:
! 270: /* If field not present, assign it the default value */
! 271: if ((bits[i / 8] & (1 << (i % 8))) == 0) {
! 272: if (structs_init(field->type, NULL, fdata) == -1)
! 273: goto fail;
! 274: continue;
! 275: }
! 276:
! 277: /* Decode field */
! 278: if ((fclen = (*field->type->decode)(field->type,
! 279: code, cmax, fdata, ebuf, emax)) == -1)
! 280: goto fail;
! 281:
! 282: /* Go to next encoded field */
! 283: code += fclen;
! 284: cmax -= fclen;
! 285: clen += fclen;
! 286: continue;
! 287:
! 288: /* Un-do work done so far */
! 289: fail: while (i-- > 0) {
! 290: const struct structs_field *const field2
! 291: = (struct structs_field *)type->args[0].v + i;
! 292: void *const fdata2 = (char *)data + field2->offset;
! 293:
! 294: structs_free(field2->type, NULL, fdata2);
! 295: }
! 296: return (-1);
! 297: }
! 298:
! 299: /* Done */
! 300: return (clen);
! 301: }
! 302:
! 303: void
! 304: structs_struct_free(const struct structs_type *type, void *data)
! 305: {
! 306: const struct structs_field *field;
! 307:
! 308: /* Make sure it's really a structure type */
! 309: if (type->tclass != STRUCTS_TYPE_STRUCTURE)
! 310: return;
! 311:
! 312: /* Free all fields */
! 313: for (field = type->args[0].v; field->name != NULL; field++) {
! 314: (*field->type->uninit)(field->type,
! 315: (char *)data + field->offset);
! 316: }
! 317: memset((char *)data, 0, type->size);
! 318: }
! 319:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>