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,
37 gras_ddt_scalar_type_t type,
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;
46 TRY(gras_ddt_new(name,dst));
49 for (arch = 0; arch < gras_arch_count; arch ++) {
53 res->size[arch] = gras_arch_sizes[arch].sizeof_scalars[type];
58 /* just in case you wonder, x>>1 == x/2 on all architectures when x>=0 and a size is always>=0 */
60 /* make sure mask have all the bits under the biggest one of size set to 1
61 Example: size=000100101 => mask=0000111111 */
66 if (res->size[arch] & (mask >> 1)) { /* if size have bits to one beside its biggest */
67 /* size is not a power of 2 */
68 /* alignment= next power of 2 after size */
69 res->alignment[arch] = (res->size[arch] & ~(mask >> 1)) << 1;
70 gras_assert0(res->alignment[arch] != 0,
71 "scalar type too large");
73 res->aligned_size[arch] = aligned(res->size[arch], res->alignment[arch]);
74 gras_assert0 (res->aligned_size[arch] >= 0,
75 "scalar type too large");
78 /* size is a power of 2, life is great */
79 res->alignment[arch] = res->size[arch];
80 res->aligned_size[arch] = res->size[arch];
83 /* FIXME size < 0 sometimes?
86 res->aligned_size = 0;
91 res->category_code = e_gras_datadesc_type_cat_scalar;
92 res->category.scalar_data.encoding = encoding;
100 * gras_dd_cat_field_free:
102 * Frees one struct or union field
104 void gras_dd_cat_field_free(void *f) {
105 gras_dd_cat_field_t *field = (gras_dd_cat_field_t *)f;
114 * gras_ddt_new_struct:
116 * Create a new struct and give a pointer to it
119 gras_ddt_new_struct(const char *name,
120 gras_datadesc_type_cb_void_t pre,
121 gras_datadesc_type_cb_void_t post,
122 gras_datadesc_type_t **dst) {
124 gras_error_t errcode;
125 gras_datadesc_type_t *res;
128 TRY(gras_ddt_new(name,dst));
131 for (arch=0; arch<gras_arch_count; arch ++) {
133 res->alignment[arch] = 0;
134 res->aligned_size[arch] = 0;
136 res->category_code = e_gras_datadesc_type_cat_struct;
137 TRY(gras_dynar_new(&(res->category.struct_data.fields),
138 sizeof(gras_dd_cat_field_t*),
139 &gras_dd_cat_field_free));
147 * gras_ddt_new_struct_append:
149 * Append a field to the struct
152 gras_ddt_new_struct_append(gras_datadesc_type_t *struct_type,
154 gras_datadesc_type_t *field_type,
155 gras_datadesc_type_cb_void_t pre,
156 gras_datadesc_type_cb_void_t post) {
158 gras_error_t errcode;
159 gras_dd_cat_field_t *field;
162 gras_assert0(field_type->size >= 0,
163 "Cannot add a dynamically sized field in a structure");
165 field=malloc(sizeof(gras_dd_cat_field_t));
169 field->name = strdup(name);
171 for (arch=0; arch<gras_arch_count; arch ++) {
172 field->offset[arch] = aligned(struct_type->size[arch], field_type->alignment[arch]);
174 field->code = field_type->code;
178 TRY(gras_dynar_push(struct_type->category.struct_data.fields, field));
180 for (arch=0; arch<gras_arch_count; arch ++) {
181 struct_type->size[arch] = field->offset[arch] + field_type->size[arch];
182 struct_type->alignment[arch] = max(struct_type->alignment[arch], field_type->alignment[arch]);
183 struct_type->aligned_size[arch] = aligned(struct_type->size[arch], struct_type->alignment[arch]);
190 * gras_ddt_new_union:
192 * Create a new union and give a pointer to it
195 gras_ddt_new_union(const char *name,
196 gras_datadesc_type_cb_int_t field_count,
197 gras_datadesc_type_cb_void_t post,
198 gras_datadesc_type_t **dst) {
200 gras_error_t errcode;
201 gras_datadesc_type_t *res;
204 gras_assert0(field_count,
205 "Attempt to creat an union without field_count function");
207 TRY(gras_ddt_new(name,dst));
210 for (arch=0; arch<gras_arch_count; arch ++) {
212 res->alignment[arch] = 0;
213 res->aligned_size[arch] = 0;
215 res->category_code = e_gras_datadesc_type_cat_union;
216 TRY(gras_dynar_new(&(res->category.union_data.fields),
217 sizeof(gras_dd_cat_field_t*),
218 &gras_dd_cat_field_free));
219 res->category.union_data.field_count = field_count;
227 * gras_ddt_new_union_append:
229 * Append a field to the union
232 gras_ddt_new_union_append(gras_datadesc_type_t *union_type,
234 gras_datadesc_type_t *field_type,
235 gras_datadesc_type_cb_void_t pre,
236 gras_datadesc_type_cb_void_t post) {
238 gras_error_t errcode;
239 gras_dd_cat_field_t *field;
242 gras_assert0(field_type->size >= 0,
243 "Cannot add a dynamically sized field in an union");
245 field=malloc(sizeof(gras_dd_cat_field_t));
249 field->name = strdup(name);
250 for (arch=0; arch<gras_arch_count; arch ++) {
251 field->offset[arch] = 0; /* that's the purpose of union ;) */
253 field->code = field_type->code;
257 TRY(gras_dynar_push(union_type->category.union_data.fields, field));
259 for (arch=0; arch<gras_arch_count; arch ++) {
260 union_type->size[arch] = max(union_type->size[arch], field_type->size[arch]);
261 union_type->alignment[arch] = max(union_type->alignment[arch], field_type->alignment[arch]);
262 union_type->aligned_size[arch] = aligned(union_type->size[arch], union_type->alignment[arch]);
271 * Create a new ref and give a pointer to it
274 gras_ddt_new_ref(const char *name,
275 gras_datadesc_type_t *referenced_type,
276 gras_datadesc_type_cb_int_t discriminant,
277 gras_datadesc_type_cb_void_t post,
278 gras_datadesc_type_t **dst) {
280 gras_error_t errcode;
281 gras_datadesc_type_t *res;
284 gras_assert0(discriminant || referenced_type,
285 "Attempt to create a generic reference without discriminant");
287 TRY(gras_ddt_new(name,dst));
290 /* FIXME: Size from bootstraping */
291 for (arch=0; arch<gras_arch_count; arch ++) {
293 res->alignment[arch] = 0;
294 res->aligned_size[arch] = 0;
297 res->category_code = e_gras_datadesc_type_cat_ref;
299 res->category.ref_data.code = referenced_type ? referenced_type->code : -1;
300 res->category.ref_data.discriminant = discriminant;
308 * gras_ddt_new_array:
310 * Create a new array and give a pointer to it
313 gras_ddt_new_array(const char *name,
314 gras_datadesc_type_t *element_type,
316 gras_datadesc_type_cb_int_t dynamic_size,
317 gras_datadesc_type_cb_void_t post,
318 gras_datadesc_type_t **dst) {
320 gras_error_t errcode;
321 gras_datadesc_type_t *res;
324 gras_assert0(dynamic_size || fixed_size>0,
325 "Attempt to create a dynamic array without size discriminant");
327 TRY(gras_ddt_new(name,dst));
330 for (arch=0; arch<gras_arch_count; arch ++) {
331 if (fixed_size <= 0) {
332 res->size[arch] = fixed_size; /* make sure it indicates "dynamic" */
334 res->size[arch] = fixed_size * element_type->aligned_size[arch];
336 res->alignment[arch] = element_type->alignment[arch];
337 res->aligned_size[arch] = fixed_size; /*FIXME: That was so in GS, but looks stupid*/
339 res->category_code = e_gras_datadesc_type_cat_array;
341 res->category.array_data.code = element_type->code;
342 res->category.array_data.fixed_size = fixed_size;
343 res->category.array_data.dynamic_size = dynamic_size;
352 * gras_ddt_new_ignored:
354 * Create a new ignored field and give a pointer to it.
356 * If you give a default value, it will be copied away so that you can free your copy.
359 gras_ddt_new_ignored(const char *name,
361 void_f_pvoid_t *free_func,
364 gras_datadesc_type_cb_void_t post,
365 gras_datadesc_type_t **dst) {
368 gras_error_t errcode;
369 gras_datadesc_type_t *res;
371 TRY(gras_ddt_new(name,dst));
374 res->size = size > 0?size:0;
375 res->alignment = alignment;
378 res->aligned_size = aligned(size, alignment);
380 res->aligned_size = 0;
383 if (default_value && res->size) {
384 res->category.ignored_data.default_value = malloc((size_t)size);
385 if (! (res->category.ignored_data.default_value) )
387 memcpy(res->category.ignored_data.default_value,
388 default_value, (size_t)size);
391 res->category_code = e_gras_datadesc_type_cat_ignored;
392 res->category.ignored_data.free_func = free_func;
404 * gras_ddt_new_parse:
406 * Create a datadescription from the result of parsing the C type description
409 gras_ddt_new_parse(const char *name,
410 const char *C_statement,
411 gras_datadesc_type_t **dst) {
417 gras_ddt_new_from_nws(const char *name,
418 const DataDescriptor *desc,
420 gras_datadesc_type_t **dst) {
427 * Frees a datadescription.
429 void gras_ddt_free(gras_datadesc_type_t **type) {
430 gras_datadesc_type_t *t;
436 switch (t->category_code) {
437 case e_gras_datadesc_type_cat_scalar:
438 case e_gras_datadesc_type_cat_ref:
439 case e_gras_datadesc_type_cat_array:
440 /* nothing to free in there */
443 case e_gras_datadesc_type_cat_ignored:
444 if (t->category.ignored_data.free_func) {
445 t->category.ignored_data.free_func(t->category.ignored_data.default_value);
449 case e_gras_datadesc_type_cat_struct:
450 gras_dynar_free(t->category.struct_data.fields);
453 case e_gras_datadesc_type_cat_union:
454 gras_dynar_free(t->category.union_data.fields);
458 /* datadesc was invalid. Killing it is like euthanasy, I guess */