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>