Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
82a7ba47f55e012a4e5053a87394f52d68c268be
[simgrid.git] / src / gras / DataDesc / ddt_create.c
1 /* $Id$ */
2
3 /* ddt_new - creation/deletion of datatypes structs (private to this module)*/
4
5 /* Authors: Olivier Aumage, Martin Quinson                                  */
6 /* Copyright (C) 2003, 2004 the GRAS posse.                                 */
7
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. */
10
11 #include "DataDesc/datadesc_private.h"
12
13 GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(new,DataDesc);
14
15 /**
16  * gras_ddt_freev:
17  *
18  * gime that memory back, dude. I mean it.
19  */
20 static void gras_ddt_freev(void *ddt) {
21   gras_datadesc_type_t *type= (gras_datadesc_type_t *)ddt;
22   
23   if (type) {
24     gras_datadesc_unref(type);
25   }
26 }
27
28 static gras_error_t
29 gras_ddt_new(const char            *name,
30              gras_datadesc_type_t **dst) {
31
32   gras_error_t errcode;
33   gras_datadesc_type_t *res;
34
35   res=malloc(sizeof(gras_datadesc_type_t));
36   if (!res) 
37     RAISE_MALLOC;
38
39   memset(res, 0, sizeof(gras_datadesc_type_t));
40   res->name = strdup(name);
41   res->name_len = strlen(name);
42   res->refcounter = 1;
43   
44   TRY(gras_set_add(gras_datadesc_set_local,
45                    (gras_set_elm_t*)res,&gras_ddt_freev));
46     
47   *dst=res;
48   return no_error;
49 }
50
51 /**
52  * gras_datadesc_by_name:
53  *
54  * Retrieve a type from its name
55  */
56 gras_datadesc_type_t *gras_datadesc_by_name(const char *name) {
57
58   gras_datadesc_type_t *type;
59
60   if (gras_set_get_by_name(gras_datadesc_set_local,
61                            name,(gras_set_elm_t**)&type) == no_error) {
62     return type;
63   } else { 
64     return NULL;
65   }
66 }
67
68 /**
69  * gras_datadesc_by_id:
70  *
71  * Retrieve a type from its code
72  */
73 gras_error_t gras_datadesc_by_id(long int               code,
74                                  gras_datadesc_type_t **type) {
75   return gras_set_get_by_id(gras_datadesc_set_local,
76                             code,(gras_set_elm_t**)type);
77 }
78
79 /**
80  * gras_datadesc_declare_scalar:
81  *
82  * Create a new scalar and give a pointer to it 
83  */
84 gras_error_t 
85 gras_datadesc_declare_scalar(const char                      *name,
86                         gras_ddt_scalar_type_t           type,
87                         enum e_gras_dd_scalar_encoding   encoding,
88                         gras_datadesc_type_cb_void_t     cb,
89                         gras_datadesc_type_t           **dst) {
90
91   gras_error_t errcode;
92   gras_datadesc_type_t *res;
93   long int arch;
94
95   TRY(gras_ddt_new(name,dst));
96   res=*dst;
97
98   for (arch = 0; arch < gras_arch_count; arch ++) {
99     long int sz;
100     long int mask;
101
102     res->size[arch] = gras_arches[arch].sizeof_scalars[type];
103     
104     sz = res->size[arch];
105     mask = sz;
106     
107     /* just in case you wonder, x>>1 == x/2 on all architectures when x>=0 and a size is always>=0 */
108
109     /* make sure mask have all the bits under the biggest one of size set to 1
110        Example: size=000100101 => mask=0000111111 */
111     while ((sz >>= 1)) {
112       mask |= sz;
113     }
114     
115     if (res->size[arch] & (mask >> 1)) { /* if size have bits to one beside its biggest */
116       /* size is not a power of 2 */
117       /* alignment= next power of 2 after size */
118       res->alignment[arch] = (res->size[arch] & ~(mask >> 1)) << 1;
119       gras_assert0(res->alignment[arch] != 0,
120                    "scalar type too large");
121       
122       res->aligned_size[arch]    = aligned(res->size[arch], res->alignment[arch]);
123       gras_assert0 (res->aligned_size[arch] >= 0,
124                     "scalar type too large");
125       
126     } else {
127       /* size is a power of 2, life is great */
128       res->alignment[arch]       = res->size[arch];
129       res->aligned_size[arch]    = res->size[arch];
130     }
131
132     /* FIXME size < 0 sometimes? 
133        } else {
134        res->alignment    = 0;
135        res->aligned_size = 0;
136        }
137     */
138   }
139
140   res->category_code                 = e_gras_datadesc_type_cat_scalar;
141   res->category.scalar_data.encoding = encoding;
142
143   res->pre = cb;
144   return no_error;
145 }
146
147
148 /**
149  * gras_dd_cat_field_free:
150  *
151  * Frees one struct or union field
152  */
153 void gras_dd_cat_field_free(void *f) {
154   gras_dd_cat_field_t *field = *(gras_dd_cat_field_t **)f;
155   if (field) {
156     if (field->name) 
157       free(field->name);
158     free(field);
159   }
160 }
161
162 /**
163  * gras_datadesc_declare_struct:
164  *
165  * Create a new struct and give a pointer to it 
166  */
167 gras_error_t 
168 gras_datadesc_declare_struct(const char                      *name,
169                         gras_datadesc_type_t           **dst) {
170
171   gras_error_t errcode;
172   gras_datadesc_type_t *res;
173   long int arch;
174
175   TRY(gras_ddt_new(name,dst));
176   res=*dst;
177
178   for (arch=0; arch<gras_arch_count; arch ++) {
179     res->size[arch]                     = 0;
180     res->alignment[arch]                = 0;
181     res->aligned_size[arch]             = 0;
182   }
183   res->category_code            = e_gras_datadesc_type_cat_struct;
184   TRY(gras_dynar_new(&(res->category.struct_data.fields),
185                      sizeof(gras_dd_cat_field_t*),
186                      &gras_dd_cat_field_free));
187
188   return no_error;
189 }
190
191 /**
192  * gras_datadesc_declare_struct_append:
193  *
194  * Append a field to the struct
195  */
196 gras_error_t 
197 gras_datadesc_declare_struct_append(gras_datadesc_type_t            *struct_type,
198                                const char                      *name,
199                                gras_datadesc_type_t            *field_type) {
200
201   gras_error_t errcode;
202   gras_dd_cat_field_t *field;
203   int arch;
204
205   gras_assert0(field_type->size >= 0,
206                "Cannot add a dynamically sized field in a structure");
207     
208   field=malloc(sizeof(gras_dd_cat_field_t));
209   if (!field)
210     RAISE_MALLOC;
211
212   field->name   = strdup(name);
213
214   for (arch=0; arch<gras_arch_count; arch ++) {
215     field->offset[arch] = aligned(struct_type->size[arch], field_type->alignment[arch]);
216   }
217   field->code   = field_type->code;
218   field->pre    = NULL;
219   field->post   = NULL;
220   
221   TRY(gras_dynar_push(struct_type->category.struct_data.fields, &field));
222
223   for (arch=0; arch<gras_arch_count; arch ++) {
224     struct_type->size[arch]             = field->offset[arch] + field_type->size[arch];
225     struct_type->alignment[arch]        = max(struct_type->alignment[arch], field_type->alignment[arch]);
226     struct_type->aligned_size[arch]     = aligned(struct_type->size[arch], struct_type->alignment[arch]);
227   }
228
229   return no_error;
230 }
231
232 /**
233  * gras_datadesc_declare_union:
234  *
235  * Create a new union and give a pointer to it 
236  */
237 gras_error_t 
238 gras_datadesc_declare_union(const char                      *name,
239                    gras_datadesc_type_cb_int_t      selector,
240                    gras_datadesc_type_t           **dst) {
241
242   gras_error_t errcode;
243   gras_datadesc_type_t *res;
244   int arch;
245
246   gras_assert0(selector,
247                "Attempt to creat an union without field_count function");
248
249   TRY(gras_ddt_new(name,dst));
250   res=*dst;
251
252   for (arch=0; arch<gras_arch_count; arch ++) {
253     res->size[arch]                     = 0;
254     res->alignment[arch]                = 0;
255     res->aligned_size[arch]             = 0;
256   }
257   res->category_code            = e_gras_datadesc_type_cat_union;
258   TRY(gras_dynar_new(&(res->category.union_data.fields),
259                      sizeof(gras_dd_cat_field_t*),
260                      &gras_dd_cat_field_free));
261   res->category.union_data.selector = selector;
262
263   return no_error;
264 }
265
266 /**
267  * gras_datadesc_declare_union_append:
268  *
269  * Append a field to the union
270  */
271 gras_error_t 
272 gras_datadesc_declare_union_append(gras_datadesc_type_t            *union_type,
273                           const char                      *name,
274                           gras_datadesc_type_t            *field_type) {
275
276   gras_error_t errcode;
277   gras_dd_cat_field_t *field;
278   int arch;
279
280   gras_assert0(field_type->size >= 0,
281                "Cannot add a dynamically sized field in an union");
282     
283   field=malloc(sizeof(gras_dd_cat_field_t));
284   if (!field)
285     RAISE_MALLOC;
286
287   field->name   = strdup(name);
288   for (arch=0; arch<gras_arch_count; arch ++) {
289     field->offset[arch] = 0; /* that's the purpose of union ;) */
290   }
291   field->code   = field_type->code;
292   field->pre    = NULL;
293   field->post   = NULL;
294   
295   TRY(gras_dynar_push(union_type->category.union_data.fields, &field));
296
297   for (arch=0; arch<gras_arch_count; arch ++) {
298     union_type->size[arch]         = max(union_type->size[arch], field_type->size[arch]);
299     union_type->alignment[arch]    = max(union_type->alignment[arch], field_type->alignment[arch]);
300     union_type->aligned_size[arch] = aligned(union_type->size[arch], union_type->alignment[arch]);
301   }
302
303   return no_error;
304 }
305
306 /**
307  * gras_datadesc_declare_ref:
308  *
309  * Create a new ref to a fixed type and give a pointer to it 
310  */
311 gras_error_t 
312 gras_datadesc_declare_ref(const char             *name,
313                           gras_datadesc_type_t   *referenced_type,
314                           gras_datadesc_type_t  **dst) {
315
316   gras_error_t errcode;
317   gras_datadesc_type_t *res;
318   gras_datadesc_type_t *pointer_type = gras_datadesc_by_name("data pointer");
319   int arch;
320
321   TRY(gras_ddt_new(name,dst));
322   res=*dst;
323
324   gras_assert0(pointer_type, "Cannot get the description of data pointer");
325       
326   for (arch=0; arch<gras_arch_count; arch ++) {
327     res->size[arch]                     = pointer_type->size[arch];
328     res->alignment[arch]                = pointer_type->alignment[arch];
329     res->aligned_size[arch]             = pointer_type->aligned_size[arch];
330   }
331
332   res->category_code            = e_gras_datadesc_type_cat_ref;
333
334   res->category.ref_data.code     = referenced_type->code;
335   res->category.ref_data.selector = NULL;
336
337   return no_error;
338 }
339 /**
340  * gras_datadesc_declare_ref_generic:
341  *
342  * Create a new ref to a type given at use time, and give a pointer to it 
343  */
344 gras_error_t 
345 gras_datadesc_declare_ref_generic(const char                      *name,
346                          gras_datadesc_type_cb_int_t      selector,
347                          gras_datadesc_type_t           **dst) {
348
349   gras_error_t errcode;
350   gras_datadesc_type_t *res;
351   gras_datadesc_type_t *pointer_type = gras_datadesc_by_name("data pointer");
352   int arch;
353
354   TRY(gras_ddt_new(name,dst));
355   res=*dst;
356
357   gras_assert0(pointer_type, "Cannot get the description of data pointer");
358       
359   for (arch=0; arch<gras_arch_count; arch ++) {
360     res->size[arch]                     = pointer_type->size[arch];
361     res->alignment[arch]                = pointer_type->alignment[arch];
362     res->aligned_size[arch]             = pointer_type->aligned_size[arch];
363   }
364
365   res->category_code            = e_gras_datadesc_type_cat_ref;
366
367   res->category.ref_data.code     = -1;
368   res->category.ref_data.selector = selector;
369
370   return no_error;
371 }
372
373 /**
374  * gras_datadesc_declare_array_fixed:
375  *
376  * Create a new array and give a pointer to it 
377  */
378 gras_error_t 
379 gras_datadesc_declare_array_fixed(const char                      *name,
380                          gras_datadesc_type_t            *element_type,
381                          long int                         fixed_size,
382                          gras_datadesc_type_t           **dst) {
383
384   gras_error_t errcode;
385   gras_datadesc_type_t *res;
386   int arch;
387
388   TRY(gras_ddt_new(name,dst));
389   res=*dst;
390
391   gras_assert1(fixed_size > 0, "'%s' is a array of negative fixed size",name);
392   for (arch=0; arch<gras_arch_count; arch ++) {
393     res->size[arch] = fixed_size * element_type->aligned_size[arch];
394     res->alignment[arch]        = element_type->alignment[arch];
395     res->aligned_size[arch]     = fixed_size; /*FIXME: That was so in GS, but looks stupid*/
396   }
397   res->category_code            = e_gras_datadesc_type_cat_array;
398
399   res->category.array_data.code         = element_type->code;
400   res->category.array_data.fixed_size   = fixed_size;
401   res->category.array_data.dynamic_size = NULL;
402
403   return no_error;
404 }
405 /**
406  * gras_datadesc_declare_array_dyn:
407  *
408  * Create a new array and give a pointer to it 
409  */
410 gras_error_t 
411 gras_datadesc_declare_array_dyn(const char                      *name,
412                        gras_datadesc_type_t            *element_type,
413                        gras_datadesc_type_cb_int_t      dynamic_size,
414                        gras_datadesc_type_t           **dst) {
415
416   gras_error_t errcode;
417   gras_datadesc_type_t *res;
418   int arch;
419
420   gras_assert1(dynamic_size,
421                "'%s' is a dynamic array without size discriminant",
422                name);
423
424   TRY(gras_ddt_new(name,dst));
425   res=*dst;
426
427   for (arch=0; arch<gras_arch_count; arch ++) {
428     res->size[arch] = -1; /* make sure it indicates "dynamic" */
429     res->alignment[arch]        = element_type->alignment[arch];
430     res->aligned_size[arch]     = -1; /*FIXME: That was so in GS, but looks stupid*/
431   }
432   res->category_code            = e_gras_datadesc_type_cat_array;
433
434   res->category.array_data.code         = element_type->code;
435   res->category.array_data.fixed_size   = -1;
436   res->category.array_data.dynamic_size = dynamic_size;
437
438   return no_error;
439 }
440
441 /**
442  * gras_datadesc_declare_parse:
443  *
444  * Create a datadescription from the result of parsing the C type description
445  */
446 gras_error_t
447 gras_datadesc_parse(const char            *name,
448                     const char            *C_statement,
449                     gras_datadesc_type_t **dst) {
450   RAISE_UNIMPLEMENTED;
451 }
452
453
454 gras_error_t
455 gras_datadesc_import_nws(const char           *name,
456                          const DataDescriptor *desc,
457                          size_t                howmany,
458                          gras_datadesc_type_t **dst) {
459   RAISE_UNIMPLEMENTED;
460 }
461
462 /**
463  * gras_datadesc_cb_set_pre:
464  *
465  * Add a pre-send callback to this datadexc
466  */
467 void gras_datadesc_cb_set_pre (gras_datadesc_type_t         *type,
468                                gras_datadesc_type_cb_void_t  pre) {
469   type->pre = pre;
470 }
471 /**
472  * gras_datadesc_cb_set_post:
473  *
474  * Add a post-send callback to this datadexc
475  */
476 void gras_datadesc_cb_set_post(gras_datadesc_type_t         *type,
477                                gras_datadesc_type_cb_void_t  post) {
478   type->post = post;
479 }
480
481 /**
482  * gras_datadesc_ref:
483  *
484  * Adds a reference to the datastruct. 
485  * ddt will be freed only when the refcount becomes 0.
486  */
487 void gras_datadesc_ref(gras_datadesc_type_t *type) {
488   type->refcounter ++;
489 }
490
491 /**
492  * gras_datadesc_unref:
493  *
494  * Adds a reference to the datastruct. 
495  * ddt will be freed only when the refcount becomes 0.
496  */
497 void gras_datadesc_unref(gras_datadesc_type_t *type) {
498   type->refcounter--;
499   if (!type->refcounter) {
500     /* even the set of ddt released that type. Let's free it */
501     DEBUG1("Let's free ddt %s",type->name);
502
503     free(type->name);
504     switch (type->category_code) {
505     case e_gras_datadesc_type_cat_scalar:
506     case e_gras_datadesc_type_cat_ref:
507     case e_gras_datadesc_type_cat_array:
508       /* nothing to free in there */
509       break;
510
511     case e_gras_datadesc_type_cat_ignored:
512       if (type->category.ignored_data.free_func) {
513         type->category.ignored_data.free_func
514           (type->category.ignored_data.default_value);
515       }
516       break;
517
518     case e_gras_datadesc_type_cat_struct:
519       gras_dynar_free(type->category.struct_data.fields);
520       break;
521
522     case e_gras_datadesc_type_cat_union:
523       gras_dynar_free(type->category.union_data.fields);
524       break;
525       
526     default:
527       /* datadesc was invalid. Killing it is like euthanasy, I guess */
528       break;
529     }
530     free(type);
531   }
532 }