Annotation of embedaddon/mpd/src/contrib/libpdel/structs/type/structs_type_struct.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/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>