Annotation of embedaddon/libpdel/structs/type/structs_type_union.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: 
                     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>