Annotation of embedaddon/libpdel/structs/type/structs_type_union.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/string.h"
! 53: #include "structs/type/union.h"
! 54: #include "util/typed_mem.h"
! 55:
! 56: /*********************************************************************
! 57: PUBLIC FUNCTIONS
! 58: *********************************************************************/
! 59:
! 60: int
! 61: structs_union_set(const struct structs_type *type, const char *name,
! 62: void *data, const char *field_name)
! 63: {
! 64: const struct structs_ufield *fields;
! 65: const struct structs_ufield *ofield;
! 66: const struct structs_ufield *field;
! 67: struct structs_union *un;
! 68: const char *mtype;
! 69: void *new_un;
! 70:
! 71: /* Find item */
! 72: if ((type = structs_find(type, name, (void **)&data, 0)) == NULL)
! 73: return (-1);
! 74:
! 75: /* Sanity check */
! 76: if (type->tclass != STRUCTS_TYPE_UNION) {
! 77: errno = EINVAL;
! 78: return (-1);
! 79: }
! 80:
! 81: /* Get union info */
! 82: fields = type->args[0].v;
! 83: mtype = type->args[1].s;
! 84: un = data;
! 85:
! 86: /* Find the old field */
! 87: for (ofield = fields; ofield->name != NULL
! 88: && strcmp(ofield->name, un->field_name) != 0; ofield++);
! 89: if (ofield->name == NULL) {
! 90: assert(0);
! 91: errno = EINVAL;
! 92: return (-1);
! 93: }
! 94:
! 95: /* Check if the union is already set to the desired field */
! 96: if (strcmp(un->field_name, field_name) == 0)
! 97: return (0);
! 98:
! 99: /* Find the new field */
! 100: for (field = fields; field->name != NULL
! 101: && strcmp(field->name, field_name) != 0; field++);
! 102: if (field->name == NULL) {
! 103: errno = ENOENT;
! 104: return (-1);
! 105: }
! 106:
! 107: /* Create a new union with the new field type */
! 108: if ((new_un = MALLOC(mtype, field->type->size)) == NULL)
! 109: return (-1);
! 110: if ((*field->type->init)(field->type, new_un) == -1) {
! 111: FREE(mtype, new_un);
! 112: return (-1);
! 113: }
! 114:
! 115: /* Replace existing union with new one having desired type */
! 116: (*ofield->type->uninit)(ofield->type, un->un);
! 117: FREE(mtype, un->un);
! 118: un->un = new_un;
! 119:
! 120: /* Set field name */
! 121: *((const char **)&un->field_name) = field->name;
! 122: return (0);
! 123: }
! 124:
! 125: /*********************************************************************
! 126: UNION TYPE METHODS
! 127: *********************************************************************/
! 128:
! 129: int
! 130: structs_union_init(const struct structs_type *type, void *data)
! 131: {
! 132: const struct structs_ufield *const field = type->args[0].v;
! 133: const char *const mtype = type->args[1].s;
! 134: struct structs_union *const un = data;
! 135:
! 136: /* Sanity */
! 137: if (field->name == NULL) {
! 138: errno = EINVAL;
! 139: return (-1);
! 140: }
! 141: assert(type->tclass == STRUCTS_TYPE_UNION);
! 142:
! 143: /* Allocate union memory */
! 144: if ((un->un = MALLOC(mtype, field->type->size)) == NULL)
! 145: return (-1);
! 146:
! 147: /* Initialize field using first member type */
! 148: if ((*field->type->init)(field->type, un->un) == -1) {
! 149: FREE(mtype, un->un);
! 150: return (-1);
! 151: }
! 152:
! 153: /* Set field name */
! 154: *((const char **)&un->field_name) = field->name;
! 155: return (0);
! 156: }
! 157:
! 158: int
! 159: structs_union_copy(const struct structs_type *type, const void *from, void *to)
! 160: {
! 161: const struct structs_union *const fun = from;
! 162: const struct structs_ufield *const fields = type->args[0].v;
! 163: const struct structs_ufield *field;
! 164: const char *const mtype = type->args[1].s;
! 165: struct structs_union *const tun = to;
! 166:
! 167: /* Sanity check */
! 168: assert(type->tclass == STRUCTS_TYPE_UNION);
! 169:
! 170: /* Find field */
! 171: for (field = fields; field->name != NULL
! 172: && strcmp(fun->field_name, field->name) != 0; field++);
! 173: if (field->name == NULL) {
! 174: assert(0);
! 175: errno = EINVAL;
! 176: return (-1);
! 177: }
! 178:
! 179: /* Allocate copy union */
! 180: if ((tun->un = MALLOC(mtype, field->type->size)) == NULL)
! 181: return (-1);
! 182:
! 183: /* Copy field */
! 184: if ((*field->type->copy)(field->type, fun->un, tun->un) == -1) {
! 185: FREE(mtype, tun->un);
! 186: return (-1);
! 187: }
! 188:
! 189: /* Set field name */
! 190: *((const char **)&tun->field_name) = fun->field_name;
! 191: return (0);
! 192: }
! 193:
! 194: int
! 195: structs_union_equal(const struct structs_type *type,
! 196: const void *v1, const void *v2)
! 197: {
! 198: const struct structs_union *const un1 = v1;
! 199: const struct structs_union *const un2 = v2;
! 200: const struct structs_ufield *const fields = type->args[0].v;
! 201: const struct structs_ufield *field;
! 202:
! 203: /* Sanity check */
! 204: assert(type->tclass == STRUCTS_TYPE_UNION);
! 205:
! 206: /* Check if fields are the same */
! 207: if (strcmp(un1->field_name, un2->field_name) != 0)
! 208: return (0);
! 209:
! 210: /* Find field */
! 211: for (field = fields; field->name != NULL
! 212: && strcmp(un1->field_name, field->name) != 0; field++);
! 213: if (field->name == NULL) {
! 214: assert(0);
! 215: errno = EINVAL;
! 216: return (-1);
! 217: }
! 218:
! 219: /* Compare them */
! 220: return ((*field->type->equal)(field->type, un1->un, un2->un));
! 221: }
! 222:
! 223: int
! 224: structs_union_encode(const struct structs_type *type, const char *mtype,
! 225: struct structs_data *code, const void *data)
! 226: {
! 227: const struct structs_union *const un = data;
! 228: const struct structs_ufield *const fields = type->args[0].v;
! 229: const struct structs_ufield *field;
! 230: struct structs_data ncode;
! 231: struct structs_data fcode;
! 232:
! 233: /* Sanity check */
! 234: assert(type->tclass == STRUCTS_TYPE_UNION);
! 235:
! 236: /* Find field */
! 237: for (field = fields; field->name != NULL
! 238: && strcmp(un->field_name, field->name) != 0; field++);
! 239: if (field->name == NULL) {
! 240: assert(0);
! 241: errno = EINVAL;
! 242: return (-1);
! 243: }
! 244:
! 245: /* Encode name */
! 246: if (structs_string_encode(&structs_type_string,
! 247: TYPED_MEM_TEMP, &ncode, &field->name) == -1)
! 248: return (-1);
! 249:
! 250: /* Encode field */
! 251: if ((*field->type->encode)(field->type,
! 252: TYPED_MEM_TEMP, &fcode, un->un) == -1) {
! 253: FREE(TYPED_MEM_TEMP, ncode.data);
! 254: return (-1);
! 255: }
! 256:
! 257: /* Allocate code buffer */
! 258: code->length = ncode.length + fcode.length;
! 259: if ((code->data = MALLOC(mtype, code->length)) == NULL) {
! 260: FREE(TYPED_MEM_TEMP, fcode.data);
! 261: FREE(TYPED_MEM_TEMP, ncode.data);
! 262: return (-1);
! 263: }
! 264:
! 265: /* Copy encoded name and field */
! 266: memcpy(code->data, ncode.data, ncode.length);
! 267: memcpy(code->data + ncode.length, fcode.data, fcode.length);
! 268:
! 269: /* Done */
! 270: FREE(TYPED_MEM_TEMP, ncode.data);
! 271: FREE(TYPED_MEM_TEMP, fcode.data);
! 272: return (0);
! 273: }
! 274:
! 275: int
! 276: structs_union_decode(const struct structs_type *type, const u_char *code,
! 277: size_t cmax, void *data, char *ebuf, size_t emax)
! 278: {
! 279: const struct structs_ufield *const fields = type->args[0].v;
! 280: const char *const mtype = type->args[1].s;
! 281: struct structs_union *const un = data;
! 282: const struct structs_ufield *field;
! 283: char *field_name;
! 284: int nlen;
! 285: int flen;
! 286:
! 287: /* Sanity check */
! 288: assert(type->tclass == STRUCTS_TYPE_UNION);
! 289:
! 290: /* Decode field name */
! 291: if ((nlen = structs_string_decode(&structs_type_string,
! 292: code, cmax, &field_name, ebuf, emax)) == -1)
! 293: return (-1);
! 294:
! 295: /* Find field */
! 296: for (field = fields; field->name != NULL
! 297: && strcmp(field_name, field->name) != 0; field++);
! 298: if (field->name == NULL) {
! 299: snprintf(ebuf, emax, "unknown union field \"%s\"", field_name);
! 300: FREE(STRUCTS_TYPE_STRING_MTYPE, field_name);
! 301: return (-1);
! 302: }
! 303: FREE(STRUCTS_TYPE_STRING_MTYPE, field_name);
! 304:
! 305: /* Allocate field memory */
! 306: if ((un->un = MALLOC(mtype, field->type->size)) == NULL) {
! 307: memset(un, 0, sizeof(*un));
! 308: return (-1);
! 309: }
! 310:
! 311: /* Decode field */
! 312: if ((flen = (*field->type->decode)(field->type,
! 313: code + nlen, cmax - nlen, un->un, ebuf, emax)) == -1) {
! 314: FREE(mtype, un->un);
! 315: memset(un, 0, sizeof(*un));
! 316: return (-1);
! 317: }
! 318:
! 319: /* Set field name */
! 320: *((const char **)&un->field_name) = field->name;
! 321: return (nlen + flen);
! 322: }
! 323:
! 324: void
! 325: structs_union_free(const struct structs_type *type, void *data)
! 326: {
! 327: const char *const mtype = type->args[1].s;
! 328: const struct structs_union *const un = data;
! 329: const struct structs_ufield *const fields = type->args[0].v;
! 330: const struct structs_ufield *field;
! 331:
! 332: /* Sanity check */
! 333: assert(type->tclass == STRUCTS_TYPE_UNION);
! 334:
! 335: /* Find field */
! 336: for (field = fields; field->name != NULL
! 337: && strcmp(un->field_name, field->name) != 0; field++);
! 338: if (field->name == NULL) {
! 339: assert(0);
! 340: return;
! 341: }
! 342:
! 343: /* Free it */
! 344: (*field->type->uninit)(field->type, un->un);
! 345: FREE(mtype, un->un);
! 346: }
! 347:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>