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>