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);
25 res->name_len = strlen(name);
34 * gras_ddt_new_scalar:
36 * Create a new scalar and give a pointer to it
39 gras_ddt_new_scalar(const char *name,
40 gras_ddt_scalar_type_t type,
41 enum e_gras_dd_scalar_encoding encoding,
42 gras_datadesc_type_cb_void_t cb,
43 gras_datadesc_type_t **dst) {
46 gras_datadesc_type_t *res;
49 TRY(gras_ddt_new(name,dst));
52 for (arch = 0; arch < gras_arch_count; arch ++) {
56 res->size[arch] = gras_arch_sizes[arch].sizeof_scalars[type];
61 /* just in case you wonder, x>>1 == x/2 on all architectures when x>=0 and a size is always>=0 */
63 /* make sure mask have all the bits under the biggest one of size set to 1
64 Example: size=000100101 => mask=0000111111 */
69 if (res->size[arch] & (mask >> 1)) { /* if size have bits to one beside its biggest */
70 /* size is not a power of 2 */
71 /* alignment= next power of 2 after size */
72 res->alignment[arch] = (res->size[arch] & ~(mask >> 1)) << 1;
73 gras_assert0(res->alignment[arch] != 0,
74 "scalar type too large");
76 res->aligned_size[arch] = aligned(res->size[arch], res->alignment[arch]);
77 gras_assert0 (res->aligned_size[arch] >= 0,
78 "scalar type too large");
81 /* size is a power of 2, life is great */
82 res->alignment[arch] = res->size[arch];
83 res->aligned_size[arch] = res->size[arch];
86 /* FIXME size < 0 sometimes?
89 res->aligned_size = 0;
94 res->category_code = e_gras_datadesc_type_cat_scalar;
95 res->category.scalar_data.encoding = encoding;
103 * gras_dd_cat_field_free:
105 * Frees one struct or union field
107 void gras_dd_cat_field_free(void *f) {
108 gras_dd_cat_field_t *field = (gras_dd_cat_field_t *)f;
117 * gras_ddt_new_struct:
119 * Create a new struct and give a pointer to it
122 gras_ddt_new_struct(const char *name,
123 gras_datadesc_type_cb_void_t pre,
124 gras_datadesc_type_cb_void_t post,
125 gras_datadesc_type_t **dst) {
127 gras_error_t errcode;
128 gras_datadesc_type_t *res;
131 TRY(gras_ddt_new(name,dst));
134 for (arch=0; arch<gras_arch_count; arch ++) {
136 res->alignment[arch] = 0;
137 res->aligned_size[arch] = 0;
139 res->category_code = e_gras_datadesc_type_cat_struct;
140 TRY(gras_dynar_new(&(res->category.struct_data.fields),
141 sizeof(gras_dd_cat_field_t*),
142 &gras_dd_cat_field_free));
150 * gras_ddt_new_struct_append:
152 * Append a field to the struct
155 gras_ddt_new_struct_append(gras_datadesc_type_t *struct_type,
157 gras_datadesc_type_t *field_type,
158 gras_datadesc_type_cb_void_t pre,
159 gras_datadesc_type_cb_void_t post) {
161 gras_error_t errcode;
162 gras_dd_cat_field_t *field;
165 gras_assert0(field_type->size >= 0,
166 "Cannot add a dynamically sized field in a structure");
168 field=malloc(sizeof(gras_dd_cat_field_t));
172 field->name = strdup(name);
174 for (arch=0; arch<gras_arch_count; arch ++) {
175 field->offset[arch] = aligned(struct_type->size[arch], field_type->alignment[arch]);
177 field->code = field_type->code;
181 TRY(gras_dynar_push(struct_type->category.struct_data.fields, &field));
183 for (arch=0; arch<gras_arch_count; arch ++) {
184 struct_type->size[arch] = field->offset[arch] + field_type->size[arch];
185 struct_type->alignment[arch] = max(struct_type->alignment[arch], field_type->alignment[arch]);
186 struct_type->aligned_size[arch] = aligned(struct_type->size[arch], struct_type->alignment[arch]);
193 * gras_ddt_new_union:
195 * Create a new union and give a pointer to it
198 gras_ddt_new_union(const char *name,
199 gras_datadesc_type_cb_int_t selector,
200 gras_datadesc_type_cb_void_t post,
201 gras_datadesc_type_t **dst) {
203 gras_error_t errcode;
204 gras_datadesc_type_t *res;
207 gras_assert0(selector,
208 "Attempt to creat an union without field_count function");
210 TRY(gras_ddt_new(name,dst));
213 for (arch=0; arch<gras_arch_count; arch ++) {
215 res->alignment[arch] = 0;
216 res->aligned_size[arch] = 0;
218 res->category_code = e_gras_datadesc_type_cat_union;
219 TRY(gras_dynar_new(&(res->category.union_data.fields),
220 sizeof(gras_dd_cat_field_t*),
221 &gras_dd_cat_field_free));
222 res->category.union_data.selector = selector;
230 * gras_ddt_new_union_append:
232 * Append a field to the union
235 gras_ddt_new_union_append(gras_datadesc_type_t *union_type,
237 gras_datadesc_type_t *field_type,
238 gras_datadesc_type_cb_void_t pre,
239 gras_datadesc_type_cb_void_t post) {
241 gras_error_t errcode;
242 gras_dd_cat_field_t *field;
245 gras_assert0(field_type->size >= 0,
246 "Cannot add a dynamically sized field in an union");
248 field=malloc(sizeof(gras_dd_cat_field_t));
252 field->name = strdup(name);
253 for (arch=0; arch<gras_arch_count; arch ++) {
254 field->offset[arch] = 0; /* that's the purpose of union ;) */
256 field->code = field_type->code;
260 TRY(gras_dynar_push(union_type->category.union_data.fields, &field));
262 for (arch=0; arch<gras_arch_count; arch ++) {
263 union_type->size[arch] = max(union_type->size[arch], field_type->size[arch]);
264 union_type->alignment[arch] = max(union_type->alignment[arch], field_type->alignment[arch]);
265 union_type->aligned_size[arch] = aligned(union_type->size[arch], union_type->alignment[arch]);
274 * Create a new ref and give a pointer to it
277 gras_ddt_new_ref(const char *name,
278 gras_datadesc_type_t *referenced_type,
279 gras_datadesc_type_cb_int_t selector,
280 gras_datadesc_type_cb_void_t post,
281 gras_datadesc_type_t **dst) {
283 gras_error_t errcode;
284 gras_datadesc_type_t *res;
285 gras_datadesc_type_t *pointer_type;
288 gras_assert0(selector || referenced_type,
289 "Attempt to create a generic reference without selector");
291 TRY(gras_ddt_new(name,dst));
294 TRY(gras_datadesc_by_name("data pointer", &pointer_type));
296 for (arch=0; arch<gras_arch_count; arch ++) {
297 res->size[arch] = pointer_type->size[arch];
298 res->alignment[arch] = pointer_type->alignment[arch];
299 res->aligned_size[arch] = pointer_type->aligned_size[arch];
302 res->category_code = e_gras_datadesc_type_cat_ref;
304 res->category.ref_data.code = referenced_type ? referenced_type->code : -1;
305 res->category.ref_data.selector = selector;
313 * gras_ddt_new_array:
315 * Create a new array and give a pointer to it
318 gras_ddt_new_array(const char *name,
319 gras_datadesc_type_t *element_type,
321 gras_datadesc_type_cb_int_t dynamic_size,
322 gras_datadesc_type_cb_void_t post,
323 gras_datadesc_type_t **dst) {
325 gras_error_t errcode;
326 gras_datadesc_type_t *res;
329 gras_assert0(dynamic_size || fixed_size>0,
330 "Attempt to create a dynamic array without size discriminant");
332 TRY(gras_ddt_new(name,dst));
335 for (arch=0; arch<gras_arch_count; arch ++) {
336 if (fixed_size <= 0) {
337 res->size[arch] = fixed_size; /* make sure it indicates "dynamic" */
339 res->size[arch] = fixed_size * element_type->aligned_size[arch];
341 res->alignment[arch] = element_type->alignment[arch];
342 res->aligned_size[arch] = fixed_size; /*FIXME: That was so in GS, but looks stupid*/
344 res->category_code = e_gras_datadesc_type_cat_array;
346 res->category.array_data.code = element_type->code;
347 res->category.array_data.fixed_size = fixed_size;
348 res->category.array_data.dynamic_size = dynamic_size;
357 * gras_ddt_new_ignored:
359 * Create a new ignored field and give a pointer to it.
361 * If you give a default value, it will be copied away so that you can free your copy.
364 gras_ddt_new_ignored(const char *name,
366 void_f_pvoid_t *free_func,
369 gras_datadesc_type_cb_void_t post,
370 gras_datadesc_type_t **dst) {
373 gras_error_t errcode;
374 gras_datadesc_type_t *res;
376 TRY(gras_ddt_new(name,dst));
379 res->size = size > 0?size:0;
380 res->alignment = alignment;
383 res->aligned_size = aligned(size, alignment);
385 res->aligned_size = 0;
388 if (default_value && res->size) {
389 res->category.ignored_data.default_value = malloc((size_t)size);
390 if (! (res->category.ignored_data.default_value) )
392 memcpy(res->category.ignored_data.default_value,
393 default_value, (size_t)size);
396 res->category_code = e_gras_datadesc_type_cat_ignored;
397 res->category.ignored_data.free_func = free_func;
409 * gras_ddt_new_parse:
411 * Create a datadescription from the result of parsing the C type description
414 gras_ddt_new_parse(const char *name,
415 const char *C_statement,
416 gras_datadesc_type_t **dst) {
422 gras_ddt_new_from_nws(const char *name,
423 const DataDescriptor *desc,
425 gras_datadesc_type_t **dst) {
432 * Frees a datadescription.
434 void gras_ddt_free(gras_datadesc_type_t **type) {
435 gras_datadesc_type_t *t;
441 switch (t->category_code) {
442 case e_gras_datadesc_type_cat_scalar:
443 case e_gras_datadesc_type_cat_ref:
444 case e_gras_datadesc_type_cat_array:
445 /* nothing to free in there */
448 case e_gras_datadesc_type_cat_ignored:
449 if (t->category.ignored_data.free_func) {
450 t->category.ignored_data.free_func(t->category.ignored_data.default_value);
454 case e_gras_datadesc_type_cat_struct:
455 gras_dynar_free(t->category.struct_data.fields);
458 case e_gras_datadesc_type_cat_union:
459 gras_dynar_free(t->category.union_data.fields);
463 /* datadesc was invalid. Killing it is like euthanasy, I guess */