3 /* ddt_new - creation/deletion of datatypes structs (private to this module)*/
5 /* Authors: Olivier Aumage, Martin Quinson */
6 /* Copyright (C) 2003, 2004 the GRAS posse. */
8 /* This program is free software; you can redistribute it and/or modify it
9 under the terms of the license (GNU LGPL) which comes with this package. */
11 #include "DataDesc/datadesc_private.h"
13 GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(new,DataDesc);
16 gras_ddt_new(const char *name,
17 gras_datadesc_type_t **dst) {
19 gras_datadesc_type_t *res=malloc(sizeof(gras_datadesc_type_t));
23 memset(res, 0, sizeof(res));
24 res->name = strdup(name);
31 * gras_ddt_new_scalar:
33 * Create a new scalar and give a pointer to it
36 gras_ddt_new_scalar(const char *name,
38 enum e_gras_dd_scalar_encoding encoding,
39 gras_datadesc_type_cb_void_t cb,
40 gras_datadesc_type_t **dst) {
43 gras_datadesc_type_t *res;
45 TRY(gras_ddt_new(name,dst));
48 res->size = size>0 ? size : 0;
50 if (size>0) { /* Black magic from Oli FIXME: documentation ;)*/
58 if (size & (mask >> 1)) {
59 res->alignment = (size & ~(mask >> 1)) << 1;
60 gras_assert0(res->alignment != 0,
61 "scalar type too large");
63 res->aligned_size = aligned(size, res->alignment);
64 gras_assert0 (res->aligned_size >= 0,
65 "scalar type too large");
68 res->alignment = size & ~(mask >> 1);;
69 res->aligned_size = aligned(size, res->alignment);
74 res->aligned_size = 0;
77 res->category_code = e_gras_datadesc_type_cat_scalar;
78 res->category.scalar_data.encoding = encoding;
86 * gras_dd_cat_field_free:
88 * Frees one struct or union field
90 void gras_dd_cat_field_free(void *f) {
91 gras_dd_cat_field_t *field = (gras_dd_cat_field_t *)f;
100 * gras_ddt_new_struct:
102 * Create a new struct and give a pointer to it
105 gras_ddt_new_struct(const char *name,
106 gras_datadesc_type_cb_void_t pre,
107 gras_datadesc_type_cb_void_t post,
108 gras_datadesc_type_t **dst) {
110 gras_error_t errcode;
111 gras_datadesc_type_t *res;
113 TRY(gras_ddt_new(name,dst));
118 res->aligned_size = 0;
119 res->category_code = e_gras_datadesc_type_cat_struct;
120 TRY(gras_dynar_new(&(res->category.struct_data.fields),
121 sizeof(gras_dd_cat_field_t*),
122 &gras_dd_cat_field_free));
130 * gras_ddt_new_struct_append:
132 * Append a field to the struct
135 gras_ddt_new_struct_append(gras_datadesc_type_t *struct_type,
137 gras_datadesc_type_t *field_type,
138 gras_datadesc_type_cb_void_t pre,
139 gras_datadesc_type_cb_void_t post) {
141 gras_error_t errcode;
142 gras_dd_cat_field_t *field;
144 gras_assert0(field_type->size >= 0,
145 "Cannot add a dynamically sized field in a structure");
147 field=malloc(sizeof(gras_dd_cat_field_t));
151 field->name = strdup(name);
152 field->offset = aligned(struct_type->size, field_type->alignment);
153 field->code = field_type->code;
157 TRY(gras_dynar_push(struct_type->category.struct_data.fields, field));
159 struct_type->size = field->offset + field_type->size;
160 struct_type->alignment = max(struct_type->alignment, field_type->alignment);
161 struct_type->aligned_size = aligned(struct_type->size, struct_type->alignment);
167 * gras_ddt_new_union:
169 * Create a new union and give a pointer to it
172 gras_ddt_new_union(const char *name,
173 gras_datadesc_type_cb_int_t field_count,
174 gras_datadesc_type_cb_void_t post,
175 gras_datadesc_type_t **dst) {
177 gras_error_t errcode;
178 gras_datadesc_type_t *res;
180 gras_assert0(field_count,
181 "Attempt to creat an union without field_count function");
183 TRY(gras_ddt_new(name,dst));
188 res->aligned_size = 0;
189 res->category_code = e_gras_datadesc_type_cat_union;
190 TRY(gras_dynar_new(&(res->category.union_data.fields),
191 sizeof(gras_dd_cat_field_t*),
192 &gras_dd_cat_field_free));
193 res->category.union_data.field_count = field_count;
201 * gras_ddt_new_union_append:
203 * Append a field to the union
206 gras_ddt_new_union_append(gras_datadesc_type_t *union_type,
208 gras_datadesc_type_t *field_type,
209 gras_datadesc_type_cb_void_t pre,
210 gras_datadesc_type_cb_void_t post) {
212 gras_error_t errcode;
213 gras_dd_cat_field_t *field;
215 gras_assert0(field_type->size >= 0,
216 "Cannot add a dynamically sized field in an union");
218 field=malloc(sizeof(gras_dd_cat_field_t));
222 field->name = strdup(name);
223 field->offset = 0; /* that's the purpose of union ;) */
224 field->code = field_type->code;
228 TRY(gras_dynar_push(union_type->category.union_data.fields, field));
230 union_type->size = max(union_type->size, field_type->size);
231 union_type->alignment = max(union_type->alignment, field_type->alignment);
232 union_type->aligned_size = aligned(union_type->size, union_type->alignment);
240 * Create a new ref and give a pointer to it
243 gras_ddt_new_ref(const char *name,
244 gras_datadesc_type_t *referenced_type,
245 gras_datadesc_type_cb_int_t discriminant,
246 gras_datadesc_type_cb_void_t post,
247 gras_datadesc_type_t **dst) {
249 gras_error_t errcode;
250 gras_datadesc_type_t *res;
252 gras_assert0(discriminant || referenced_type,
253 "Attempt to create a generic reference without discriminant");
255 TRY(gras_ddt_new(name,dst));
258 /* FIXME: Size from bootstraping */
261 res->aligned_size = 0;
262 res->category_code = e_gras_datadesc_type_cat_ref;
264 res->category.ref_data.code = referenced_type ? referenced_type->code : -1;
265 res->category.ref_data.discriminant = discriminant;
273 * gras_ddt_new_array:
275 * Create a new array and give a pointer to it
278 gras_ddt_new_array(const char *name,
279 gras_datadesc_type_t *element_type,
281 gras_datadesc_type_cb_int_t dynamic_size,
282 gras_datadesc_type_cb_void_t post,
283 gras_datadesc_type_t **dst) {
285 gras_error_t errcode;
286 gras_datadesc_type_t *res;
288 gras_assert0(dynamic_size || fixed_size>0,
289 "Attempt to create a dynamic array without size discriminant");
291 TRY(gras_ddt_new(name,dst));
294 if (fixed_size <= 0) {
295 res->size = fixed_size;
297 res->size = fixed_size * element_type->aligned_size;
299 res->alignment = element_type->alignment;
300 res->aligned_size = fixed_size; /*FIXME: That was so in GS, but looks stupid*/
301 res->category_code = e_gras_datadesc_type_cat_array;
303 res->category.array_data.code = element_type->code;
304 res->category.array_data.fixed_size = fixed_size;
305 res->category.array_data.dynamic_size = dynamic_size;
314 * gras_ddt_new_ignored:
316 * Create a new ignored field and give a pointer to it.
318 * If you give a default value, it will be copied away so that you can free your copy.
321 gras_ddt_new_ignored(const char *name,
323 void_f_pvoid_t *free_func,
326 gras_datadesc_type_cb_void_t post,
327 gras_datadesc_type_t **dst) {
328 gras_error_t errcode;
329 gras_datadesc_type_t *res;
331 TRY(gras_ddt_new(name,dst));
334 res->size = size > 0?size:0;
335 res->alignment = alignment;
338 res->aligned_size = aligned(size, alignment);
340 res->aligned_size = 0;
343 if (default_value && res->size) {
344 res->category.ignored_data.default_value = malloc((size_t)size);
345 if (! (res->category.ignored_data.default_value) )
347 memcpy(res->category.ignored_data.default_value,
348 default_value, (size_t)size);
351 res->category_code = e_gras_datadesc_type_cat_ignored;
352 res->category.ignored_data.free_func = free_func;
365 * Frees a datadescription.
367 void gras_ddt_free(gras_datadesc_type_t **type) {
368 gras_datadesc_type_t *t;
374 switch (t->category_code) {
375 case e_gras_datadesc_type_cat_scalar:
376 case e_gras_datadesc_type_cat_ref:
377 case e_gras_datadesc_type_cat_array:
378 /* nothing to free in there */
381 case e_gras_datadesc_type_cat_ignored:
382 if (t->category.ignored_data.free_func) {
383 t->category.ignored_data.free_func(t->category.ignored_data.default_value);
387 case e_gras_datadesc_type_cat_struct:
388 gras_dynar_free(t->category.struct_data.fields);
391 case e_gras_datadesc_type_cat_union:
392 gras_dynar_free(t->category.union_data.fields);
396 /* datadesc was invalid. Killing it is like euthanasy, I guess */