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>