Tizen Native API  3.0
File descriptor data example, with Eet unions and variants

This is an example much like the one shown in Advanced use of Eet Data Descriptors. The difference is that here we're attaining ourselves to two new data types to store in an Eet file -- unions and variants. We don't try to come with data mapping to real world use cases, here. Instead, we're defining 3 different simple structures to be used throughout the example:

typedef struct _Example_Struct1      Example_Struct1;
typedef struct _Example_Struct2      Example_Struct2;
typedef struct _Example_Struct3      Example_Struct3;
struct _Example_Struct1
{
   double      val1;
   int         stuff;
   const char *s1;
};

struct _Example_Struct2
{
   Eina_Bool          b1;
   unsigned long long v1;
};

struct _Example_Struct3
{
   int body;
};

To identify, for both union and variant data cases, the type of each chunk of data, we're defining types to point to each of those structs:

typedef enum _Example_Data_Type      Example_Data_Type;
enum _Example_Data_Type
{
   EET_UNKNOWN = 0,
   EET_STRUCT1,
   EET_STRUCT2,
   EET_STRUCT3,
   EET_BASIC_FLOAT,
   EET_BASIC_STRING
};

We have also a mapping from those types to name strings, to be used in the Eet unions and variants type_get() and type_set() type identifying callbacks:

struct
{
   Example_Data_Type u;
   const char       *name;
} eet_mapping[] = {
   { EET_STRUCT1, "ST1" },
   { EET_STRUCT2, "ST2" },
   { EET_STRUCT3, "ST3" },
   { EET_BASIC_FLOAT, "float" },
   { EET_BASIC_STRING, "string" },
   { EET_UNKNOWN, NULL }
};

In this example, we have no fancy hash to store our data into profiles/accounts, but just two lists for union and variant data nodes:

typedef struct _Example_Lists        Example_Lists;
struct _Example_Lists
{
   Eina_List *union_list;
   Eina_List *variant_list;
};

Let's begin with our unions, then, which look like:

typedef struct _Example_Union        Example_Union;
struct _Example_Union
{
   Example_Data_Type type;

   union {
      Example_Struct1 st1;
      Example_Struct2 st2;
      Example_Struct3 st3;
      float f;
      const char* string;
   } u;
};

The first interesting part of the code is where we define our data descriptors for the main lists, the unions and all of structures upon which those two depend.

/* declaring types */
_data_descriptors_init(void)
{
   Eet_Data_Descriptor_Class eddc;

   EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Lists);
   _lists_descriptor = eet_data_descriptor_file_new(&eddc);

   _struct_1_descriptor = _st1_dd();
   _struct_2_descriptor = _st2_dd();
   _struct_3_descriptor = _st3_dd();

   /* for union */
   EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Union);
   _union_descriptor = eet_data_descriptor_file_new(&eddc);

   eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
   eddc.func.type_get = _union_type_get;
   eddc.func.type_set = _union_type_set;
   _union_unified_descriptor = eet_data_descriptor_file_new(&eddc);

   EET_DATA_DESCRIPTOR_ADD_MAPPING(
     _union_unified_descriptor, "ST1", _struct_1_descriptor);
   EET_DATA_DESCRIPTOR_ADD_MAPPING(
     _union_unified_descriptor, "ST2", _struct_2_descriptor);
   EET_DATA_DESCRIPTOR_ADD_MAPPING(
     _union_unified_descriptor, "ST3", _struct_3_descriptor);
   EET_DATA_DESCRIPTOR_ADD_MAPPING_BASIC(
     _union_unified_descriptor, "float", EET_T_FLOAT);
   EET_DATA_DESCRIPTOR_ADD_MAPPING_BASIC(
     _union_unified_descriptor, "string", EET_T_STRING);

   EET_DATA_DESCRIPTOR_ADD_UNION(
     _union_descriptor, Example_Union, "u", u, type,
     _union_unified_descriptor);

   EET_DATA_DESCRIPTOR_ADD_LIST(
     _lists_descriptor, Example_Lists, "union_list", union_list,
     _union_descriptor);
The code for descriptors on Example_Struct1, Example_Struct2 and Example_Struct3 is straightforward, a matter already covered on Advanced use of Eet Data Descriptors. What is new, here, are the two type matching functions for our unions. There, we must set the data pointer to its matching type, on _union_type_set and return the correct matching type, on _union_type_get:

With the EET_DATA_DESCRIPTOR_ADD_MAPPING calls, which follow, we make the the link between our type names and their respective structs. The code handling actual data is pretty much the same as in Advanced use of Eet Data Descriptors -- one uses command line arguments to enter new data chunks (or just to visualize the contents of an Eet file), signalling if they are unions or variants. One must also pass the type of the data chuck to enter, with integers 1, 2 or 3. Then, come the fields for each type:

                "Usage:\n\t%s <input> <output> [action action-params]\n\n"
                "where actions and their parameters are:\n"
                "\tunion <type> [fields]\n"
                "\tvariant <type> [fields]\n"
                "\n",
                argv[0]);

Variants are very similar to unions, except that data chunks need not contain previously allocated space for each of the possible types of data going in them:

typedef struct _Example_Variant_Type Example_Variant_Type;
struct _Example_Variant_Type
{
   const char *type;
   Eina_Bool   unknow : 1;
};

struct _Example_Variant
{
   Example_Variant_Type t;

   void                *data; /* differently than the union type, we
                               * don't need to pre-allocate the memory
                               * for the field*/
};

The code declaring the data descriptors and handling the data is very similar to the unions part, and is left for the reader to check for him/herself. The complete code of the example follows.

00001 //Compile with:
00002 // gcc -o eet-data-file_descriptor_02 eet-data-file_descriptor_02.c `pkg-config --cflags --libs eet eina`
00003 
00004 #include <Eina.h>
00005 #include <Eet.h>
00006 #include <stdio.h>
00007 #include <limits.h>
00008 #include <sys/types.h>
00009 #include <sys/stat.h>
00010 #include <unistd.h>
00011 
00012 typedef enum _Example_Data_Type      Example_Data_Type;
00013 typedef struct _Example_Variant_Type Example_Variant_Type;
00014 typedef struct _Example_Variant      Example_Variant;
00015 typedef struct _Example_Union        Example_Union;
00016 typedef struct _Example_Struct1      Example_Struct1;
00017 typedef struct _Example_Struct2      Example_Struct2;
00018 typedef struct _Example_Struct3      Example_Struct3;
00019 typedef struct _Example_Lists        Example_Lists;
00020 
00021 enum _Example_Data_Type
00022 {
00023    EET_UNKNOWN = 0,
00024    EET_STRUCT1,
00025    EET_STRUCT2,
00026    EET_STRUCT3,
00027    EET_BASIC_FLOAT,
00028    EET_BASIC_STRING
00029 };
00030 
00031 struct
00032 {
00033    Example_Data_Type u;
00034    const char       *name;
00035 } eet_mapping[] = {
00036    { EET_STRUCT1, "ST1" },
00037    { EET_STRUCT2, "ST2" },
00038    { EET_STRUCT3, "ST3" },
00039    { EET_BASIC_FLOAT, "float" },
00040    { EET_BASIC_STRING, "string" },
00041    { EET_UNKNOWN, NULL }
00042 };
00043 
00044 struct _Example_Struct1
00045 {
00046    double      val1;
00047    int         stuff;
00048    const char *s1;
00049 };
00050 
00051 struct _Example_Struct2
00052 {
00053    Eina_Bool          b1;
00054    unsigned long long v1;
00055 };
00056 
00057 struct _Example_Struct3
00058 {
00059    int body;
00060 };
00061 
00062 struct _Example_Union
00063 {
00064    Example_Data_Type type;
00065 
00066    union {
00067       Example_Struct1 st1;
00068       Example_Struct2 st2;
00069       Example_Struct3 st3;
00070       float f;
00071       const char* string;
00072    } u;
00073 };
00074 
00075 struct _Example_Variant_Type
00076 {
00077    const char *type;
00078    Eina_Bool   unknow : 1;
00079 };
00080 
00081 struct _Example_Variant
00082 {
00083    Example_Variant_Type t;
00084 
00085    void                *data; /* differently than the union type, we
00086                                * don't need to pre-allocate the memory
00087                                * for the field*/
00088 };
00089 
00090 struct _Example_Lists
00091 {
00092    Eina_List *union_list;
00093    Eina_List *variant_list;
00094 };
00095 
00096 static void
00097 _st1_set(Example_Struct1 *st1,
00098          double           v1,
00099          int              v2,
00100          const char      *v3)
00101 {
00102    st1->val1 = v1;
00103    st1->stuff = v2;
00104    st1->s1 = v3;
00105 } /* _st1_set */
00106 
00107 static void
00108 _st2_set(Example_Struct2   *st2,
00109          Eina_Bool          v1,
00110          unsigned long long v2)
00111 {
00112    st2->b1 = v1;
00113    st2->v1 = v2;
00114 } /* _st2_set */
00115 
00116 static void
00117 _st3_set(Example_Struct3 *st3,
00118          int              v1)
00119 {
00120    st3->body = v1;
00121 } /* _st3_set */
00122 
00123 static const char *
00124 /* union
00125    type_get() */
00126 _union_type_get(const void *data,
00127                 Eina_Bool  *unknow)
00128 {
00129    const Example_Data_Type *u = data;
00130    int i;
00131 
00132    if (unknow)
00133      *unknow = EINA_FALSE;
00134 
00135    for (i = 0; eet_mapping[i].name != NULL; ++i)
00136      if (*u == eet_mapping[i].u)
00137        return eet_mapping[i].name;
00138 
00139    if (unknow)
00140      *unknow = EINA_TRUE;
00141 
00142    return NULL;
00143 } /* _union_type_get */
00144 
00145 static Eina_Bool
00146 _union_type_set(const char *type,
00147                 void       *data,
00148                 Eina_Bool   unknow)
00149 {
00150    Example_Data_Type *u = data;
00151    int i;
00152 
00153    if (unknow)
00154      return EINA_FALSE;
00155 
00156    for (i = 0; eet_mapping[i].name != NULL; ++i)
00157      if (strcmp(eet_mapping[i].name, type) == 0)
00158        {
00159           *u = eet_mapping[i].u;
00160           return EINA_TRUE;
00161        }
00162 
00163    return EINA_FALSE;
00164 } /* _union_type_set */
00165 
00166 static const char *
00167 _variant_type_get(const void *data,
00168                   Eina_Bool  *unknow)
00169 {
00170    const Example_Variant_Type *type = data;
00171    int i;
00172 
00173    if (unknow)
00174      *unknow = type->unknow;
00175 
00176    for (i = 0; eet_mapping[i].name != NULL; ++i)
00177      if (strcmp(type->type, eet_mapping[i].name) == 0)
00178        return eet_mapping[i].name;
00179 
00180    if (unknow)
00181      *unknow = EINA_FALSE;
00182 
00183    return type->type;
00184 } /* _variant_type_get */
00185 
00186 static Eina_Bool
00187 _variant_type_set(const char *type,
00188                   void       *data,
00189                   Eina_Bool   unknow)
00190 {
00191    Example_Variant_Type *vt = data;
00192 
00193    vt->type = type;
00194    vt->unknow = unknow;
00195    return EINA_TRUE;
00196 } /* _variant_type_set */
00197 
00198 static Eet_Data_Descriptor *
00199 _st1_dd(void)
00200 {
00201    Eet_Data_Descriptor_Class eddc;
00202    Eet_Data_Descriptor *res;
00203 
00204    EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Struct1);
00205    res = eet_data_descriptor_file_new(&eddc);
00206    EET_DATA_DESCRIPTOR_ADD_BASIC(
00207      res, Example_Struct1, "val1", val1, EET_T_DOUBLE);
00208    EET_DATA_DESCRIPTOR_ADD_BASIC(
00209      res, Example_Struct1, "stuff", stuff, EET_T_INT);
00210    EET_DATA_DESCRIPTOR_ADD_BASIC(
00211      res, Example_Struct1, "s1", s1, EET_T_STRING);
00212 
00213    return res;
00214 } /* _st1_dd */
00215 
00216 static Eet_Data_Descriptor *
00217 _st2_dd(void)
00218 {
00219    Eet_Data_Descriptor_Class eddc;
00220    Eet_Data_Descriptor *res;
00221 
00222    EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Struct2);
00223    res = eet_data_descriptor_file_new(&eddc);
00224    EET_DATA_DESCRIPTOR_ADD_BASIC(
00225      res, Example_Struct2, "b1", b1, EET_T_UCHAR);
00226    EET_DATA_DESCRIPTOR_ADD_BASIC(
00227      res, Example_Struct2, "v1", v1, EET_T_ULONG_LONG);
00228 
00229    return res;
00230 } /* _st2_dd */
00231 
00232 static Eet_Data_Descriptor *
00233 _st3_dd(void)
00234 {
00235    Eet_Data_Descriptor_Class eddc;
00236    Eet_Data_Descriptor *res;
00237 
00238    EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Struct3);
00239    res = eet_data_descriptor_file_new(&eddc);
00240    EET_DATA_DESCRIPTOR_ADD_BASIC(
00241      res, Example_Struct3, "body", body, EET_T_INT);
00242 
00243    return res;
00244 } /* _st3_dd */
00245 
00246 /* string that represents the entry in the eet file. you might like to
00247  * have different profiles or so in the same file, this is possible
00248  * with different strings
00249  */
00250 static const char CACHE_FILE_ENTRY[] = "cache";
00251 
00252 /* keep the descriptor static global, so it can be shared by different
00253  * functions (load/save) of this and only this file.
00254  */
00255 static Eet_Data_Descriptor *_lists_descriptor;
00256 static Eet_Data_Descriptor *_struct_1_descriptor;
00257 static Eet_Data_Descriptor *_struct_2_descriptor;
00258 static Eet_Data_Descriptor *_struct_3_descriptor;
00259 static Eet_Data_Descriptor *_union_descriptor;
00260 static Eet_Data_Descriptor *_variant_descriptor;
00261 static Eet_Data_Descriptor *_union_unified_descriptor;
00262 static Eet_Data_Descriptor *_variant_unified_descriptor;
00263 
00264 /* keep file handle alive, so mmap()ed strings are all alive as
00265  * well */
00266 static Eet_File *_cache_file = NULL;
00267 static Eet_Dictionary *_cache_dict = NULL;
00268 
00269 static void
00270 /* declaring types */
00271 _data_descriptors_init(void)
00272 {
00273    Eet_Data_Descriptor_Class eddc;
00274 
00275    EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Lists);
00276    _lists_descriptor = eet_data_descriptor_file_new(&eddc);
00277 
00278    _struct_1_descriptor = _st1_dd();
00279    _struct_2_descriptor = _st2_dd();
00280    _struct_3_descriptor = _st3_dd();
00281 
00282    /* for union */
00283    EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Union);
00284    _union_descriptor = eet_data_descriptor_file_new(&eddc);
00285 
00286    eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
00287    eddc.func.type_get = _union_type_get;
00288    eddc.func.type_set = _union_type_set;
00289    _union_unified_descriptor = eet_data_descriptor_file_new(&eddc);
00290 
00291    EET_DATA_DESCRIPTOR_ADD_MAPPING(
00292      _union_unified_descriptor, "ST1", _struct_1_descriptor);
00293    EET_DATA_DESCRIPTOR_ADD_MAPPING(
00294      _union_unified_descriptor, "ST2", _struct_2_descriptor);
00295    EET_DATA_DESCRIPTOR_ADD_MAPPING(
00296      _union_unified_descriptor, "ST3", _struct_3_descriptor);
00297    EET_DATA_DESCRIPTOR_ADD_MAPPING_BASIC(
00298      _union_unified_descriptor, "float", EET_T_FLOAT);
00299    EET_DATA_DESCRIPTOR_ADD_MAPPING_BASIC(
00300      _union_unified_descriptor, "string", EET_T_STRING);
00301 
00302    EET_DATA_DESCRIPTOR_ADD_UNION(
00303      _union_descriptor, Example_Union, "u", u, type,
00304      _union_unified_descriptor);
00305 
00306    EET_DATA_DESCRIPTOR_ADD_LIST(
00307      _lists_descriptor, Example_Lists, "union_list", union_list,
00308      _union_descriptor);
00309 
00310    /* for variant */
00311    EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Variant);
00312    _variant_descriptor = eet_data_descriptor_file_new(&eddc);
00313 
00314    eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
00315    eddc.func.type_get = _variant_type_get;
00316    eddc.func.type_set = _variant_type_set;
00317    _variant_unified_descriptor = eet_data_descriptor_stream_new(&eddc);
00318 
00319    EET_DATA_DESCRIPTOR_ADD_MAPPING(
00320      _variant_unified_descriptor, "ST1", _struct_1_descriptor);
00321    EET_DATA_DESCRIPTOR_ADD_MAPPING(
00322      _variant_unified_descriptor, "ST2", _struct_2_descriptor);
00323    EET_DATA_DESCRIPTOR_ADD_MAPPING(
00324      _variant_unified_descriptor, "ST3", _struct_3_descriptor);
00325 
00326    EET_DATA_DESCRIPTOR_ADD_VARIANT(
00327      _variant_descriptor, Example_Variant, "data", data, t,
00328      _variant_unified_descriptor);
00329 
00330    EET_DATA_DESCRIPTOR_ADD_LIST(
00331      _lists_descriptor, Example_Lists, "variant_list", variant_list,
00332      _variant_descriptor);
00333 } /* _data_descriptors_init */
00334 
00335 static void
00336 _data_descriptors_shutdown(void)
00337 {
00338    eet_data_descriptor_free(_lists_descriptor);
00339    eet_data_descriptor_free(_struct_1_descriptor);
00340    eet_data_descriptor_free(_struct_2_descriptor);
00341    eet_data_descriptor_free(_struct_3_descriptor);
00342    eet_data_descriptor_free(_union_descriptor);
00343    eet_data_descriptor_free(_variant_descriptor);
00344    eet_data_descriptor_free(_union_unified_descriptor);
00345    eet_data_descriptor_free(_variant_unified_descriptor);
00346 } /* _data_descriptors_shutdown */
00347 
00348 /* need to check if the pointer came from mmap()ed area in
00349  * eet_dictionary or it was allocated with eina_stringshare_add()
00350  */
00351 static void
00352 _string_free(const char *str)
00353 {
00354    if (!str)
00355      return;
00356 
00357    if ((_cache_dict) && (eet_dictionary_string_check(_cache_dict, str)))
00358      return;
00359 
00360    eina_stringshare_del(str);
00361 } /* _string_free */
00362 
00363 static Example_Union *
00364 _union_1_new(const char *v1,
00365              const char *v2,
00366              const char *v3)
00367 {
00368    Example_Union *un = calloc(1, sizeof(Example_Union));
00369    if (!un)
00370      {
00371         fprintf(
00372           stderr, "ERROR: could not allocate an Example_Union struct.\n");
00373         return NULL;
00374      }
00375 
00376    un->type = EET_STRUCT1;
00377    _st1_set(&(un->u.st1), atof(v1), atoi(v2), eina_stringshare_add(v3));
00378 
00379    return un;
00380 }
00381 
00382 static Example_Union *
00383 _union_2_new(const char *v1,
00384              const char *v2)
00385 {
00386    Example_Union *un = calloc(1, sizeof(Example_Union));
00387    if (!un)
00388      {
00389         fprintf(
00390           stderr, "ERROR: could not allocate an Example_Union struct.\n");
00391         return NULL;
00392      }
00393 
00394    un->type = EET_STRUCT2;
00395    _st2_set(&(un->u.st2), atoi(v1), atoi(v2));
00396 
00397    return un;
00398 }
00399 
00400 static Example_Union *
00401 _union_3_new(const char *v1)
00402 {
00403    Example_Union *un = calloc(1, sizeof(Example_Union));
00404    if (!un)
00405      {
00406         fprintf(
00407           stderr, "ERROR: could not allocate an Example_Union struct.\n");
00408         return NULL;
00409      }
00410 
00411    un->type = EET_STRUCT3;
00412    _st3_set(&(un->u.st3), atoi(v1));
00413 
00414    return un;
00415 }
00416 
00417 static Example_Union *
00418 _union_float_new(const char *v1)
00419 {
00420    Example_Union *un = calloc(1, sizeof(Example_Union));
00421    if (!un)
00422      {
00423         fprintf(
00424           stderr, "ERROR: could not allocate an Example_Union struct.\n");
00425         return NULL;
00426      }
00427 
00428    un->type = EET_BASIC_FLOAT;
00429    un->u.f = atof(v1);
00430 
00431    return un;
00432 }
00433 
00434 static Example_Union *
00435 _union_string_new(const char *v1)
00436 {
00437    Example_Union *un = calloc(1, sizeof(Example_Union));
00438    if (!un)
00439      {
00440         fprintf(
00441           stderr, "ERROR: could not allocate an Example_Union struct.\n");
00442         return NULL;
00443      }
00444 
00445    un->type = EET_BASIC_STRING;
00446    un->u.string = v1;
00447 
00448    return un;
00449 }
00450 
00451 static Example_Variant *
00452 _variant_1_new(const char *v1,
00453                const char *v2,
00454                const char *v3)
00455 {
00456    Example_Struct1 *st1;
00457    Example_Variant *va = calloc(1, sizeof(Example_Variant));
00458    if (!va)
00459      {
00460         fprintf(
00461           stderr, "ERROR: could not allocate an Example_Variant struct.\n");
00462         return NULL;
00463      }
00464 
00465    va->t.type = eet_mapping[0].name;
00466    st1 = calloc(1, sizeof (Example_Struct1));
00467    _st1_set(st1, atof(v1), atoi(v2), eina_stringshare_add(v3));
00468    va->data = st1;
00469 
00470    return va;
00471 }
00472 
00473 static Example_Variant *
00474 _variant_2_new(const char *v1,
00475                const char *v2)
00476 {
00477    printf("varinant 2 new\n");
00478 
00479    Example_Struct2 *st2;
00480    Example_Variant *va = calloc(1, sizeof(Example_Variant));
00481    if (!va)
00482      {
00483         fprintf(
00484           stderr, "ERROR: could not allocate an Example_Variant struct.\n");
00485         return NULL;
00486      }
00487 
00488    va->t.type = eet_mapping[1].name;
00489 
00490    printf("type gets %s\n", va->t.type);
00491 
00492    st2 = calloc(1, sizeof (Example_Struct2));
00493    _st2_set(st2, atoi(v1), atoi(v2));
00494    va->data = st2;
00495 
00496    return va;
00497 }
00498 
00499 static Example_Variant *
00500 _variant_3_new(const char *v1)
00501 {
00502    Example_Struct3 *st3;
00503    Example_Variant *va = calloc(1, sizeof(Example_Variant));
00504    if (!va)
00505      {
00506         fprintf(
00507           stderr, "ERROR: could not allocate an Example_Variant struct.\n");
00508         return NULL;
00509      }
00510 
00511    va->t.type = eet_mapping[2].name;
00512    st3 = calloc(1, sizeof (Example_Struct3));
00513    _st3_set(st3, atoi(v1));
00514    va->data = st3;
00515 
00516    return va;
00517 }
00518 
00519 static Example_Lists *
00520 _data_new(void)
00521 {
00522    Example_Lists *example_lists = calloc(1, sizeof(Example_Lists));
00523    if (!example_lists)
00524      {
00525         fprintf(stderr, "ERROR: could not allocate a Example_Lists struct.\n");
00526         return NULL;
00527      }
00528 
00529    return example_lists;
00530 } /* _data_new */
00531 
00532 static void
00533 _union_free(Example_Union *un)
00534 {
00535    if (un->type == EET_STRUCT1)
00536      {
00537         Example_Struct1 *st1 = &(un->u.st1);
00538         _string_free(st1->s1);
00539      }
00540 
00541    free(un);
00542 }
00543 
00544 static void
00545 _variant_free(Example_Variant *va)
00546 {
00547    if (!strcmp(va->t.type, eet_mapping[0].name))
00548      {
00549         Example_Struct1 *st1 = va->data;
00550         _string_free(st1->s1);
00551      }
00552 
00553    free(va->data);
00554    free(va);
00555 }
00556 
00557 static void
00558 _data_free(Example_Lists *cache)
00559 {
00560    Example_Union *un;
00561    Example_Variant *va;
00562 
00563    EINA_LIST_FREE(cache->union_list, un)
00564      _union_free(un);
00565 
00566    EINA_LIST_FREE(cache->variant_list, va)
00567      _variant_free(va);
00568 
00569    free(cache);
00570 } /* _data_free */
00571 
00572 static Example_Lists *
00573 _data_load(const char *filename)
00574 {
00575    Example_Lists *data;
00576    Eet_File *ef = eet_open(filename, EET_FILE_MODE_READ);
00577    if (!ef)
00578      {
00579         fprintf(stderr, "ERROR: could not open '%s' for read\n", filename);
00580         return NULL;
00581      }
00582 
00583    data = eet_data_read(ef, _lists_descriptor, CACHE_FILE_ENTRY);
00584    if (!data)
00585      {
00586         eet_close(ef);
00587         return NULL;
00588      }
00589 
00590    if (_cache_file)
00591      eet_close(_cache_file);
00592 
00593    _cache_file = ef;
00594    _cache_dict = eet_dictionary_get(ef);
00595 
00596    return data;
00597 } /* _data_load */
00598 
00599 static Eina_Bool
00600 _data_save(const Example_Lists *cache,
00601            const char          *filename)
00602 {
00603    char tmp[PATH_MAX];
00604    Eet_File *ef;
00605    Eina_Bool ret;
00606    unsigned int i, len;
00607    struct stat st;
00608 
00609    len = eina_strlcpy(tmp, filename, sizeof(tmp));
00610    if (len + 12 >= (int)sizeof(tmp))
00611      {
00612         fprintf(stderr, "ERROR: file name is too big: %s\n", filename);
00613         return EINA_FALSE;
00614      }
00615 
00616    i = 0;
00617    do
00618      {
00619         snprintf(tmp + len, 12, ".%u", i);
00620         i++;
00621      }
00622    while (stat(tmp, &st) == 0);
00623 
00624    ef = eet_open(tmp, EET_FILE_MODE_WRITE);
00625    if (!ef)
00626      {
00627         fprintf(stderr, "ERROR: could not open '%s' for write\n", tmp);
00628         return EINA_FALSE;
00629      }
00630 
00631    ret = eet_data_write
00632        (ef, _lists_descriptor, CACHE_FILE_ENTRY, cache, EINA_TRUE);
00633 
00634    eet_close(ef);
00635 
00636    if (ret)
00637      {
00638         unlink(filename);
00639         rename(tmp, filename);
00640      }
00641 
00642    return ret;
00643 } /* _data_save */
00644 
00645 static void
00646 _print_union(const Example_Union *un)
00647 {
00648    printf("\t  |   type: %s'\n", eet_mapping[un->type - 1].name);
00649 
00650    switch (un->type)
00651      {
00652       case EET_STRUCT1:
00653         printf("\t\t  val1: %f\n", un->u.st1.val1);
00654         printf("\t\t  stuff: %d\n", un->u.st1.stuff);
00655         printf("\t\t  s1: %s\n", un->u.st1.s1);
00656         break;
00657 
00658       case EET_STRUCT2:
00659         printf("\t\t  val1: %i\n", un->u.st2.b1);
00660         printf("\t\t  stuff: %lli\n", un->u.st2.v1);
00661         break;
00662 
00663       case EET_STRUCT3:
00664         printf("\t\t  val1: %i\n", un->u.st3.body);
00665         break;
00666 
00667       case EET_BASIC_FLOAT:
00668         printf("\t\t  float: %f\n", un->u.f);
00669         break;
00670 
00671       case EET_BASIC_STRING:
00672         printf("\t\t  string: %s\n", un->u.string);
00673         break;
00674 
00675       default:
00676         return;
00677      }
00678 }
00679 
00680 static void
00681 _print_variant(const Example_Variant *va)
00682 {
00683    printf("\t  |   type: %s'\n", va->t.type);
00684 
00685    switch (va->t.type[2])
00686      {
00687       case '1':
00688       {
00689          Example_Struct1 *st1 = va->data;
00690 
00691          printf("\t\t  val1: %f\n", st1->val1);
00692          printf("\t\t  stuff: %d\n", st1->stuff);
00693          printf("\t\t  s1: %s\n", st1->s1);
00694       }
00695       break;
00696 
00697       case '2':
00698       {
00699          Example_Struct2 *st2 = va->data;
00700 
00701          printf("\t\t  val1: %i\n", st2->b1);
00702          printf("\t\t  stuff: %lli\n", st2->v1);
00703       }
00704       break;
00705 
00706       case '3':
00707       {
00708          Example_Struct3 *st3 = va->data;
00709 
00710          printf("\t\t  val1: %i\n", st3->body);
00711       }
00712       break;
00713 
00714       default:
00715         return;
00716      }
00717 }
00718 
00719 int
00720 main(int   argc,
00721      char *argv[])
00722 {
00723    Example_Lists *data_lists;
00724    int ret = 0;
00725 
00726    if (argc < 3)
00727      {
00728         fprintf(stderr,
00729                 "Usage:\n\t%s <input> <output> [action action-params]\n\n"
00730                 "where actions and their parameters are:\n"
00731                 "\tunion <type> [fields]\n"
00732                 "\tvariant <type> [fields]\n"
00733                 "\n",
00734                 argv[0]);
00735         return -1;
00736      }
00737 
00738    eina_init();
00739    eet_init();
00740    _data_descriptors_init();
00741 
00742    data_lists = _data_load(argv[1]);
00743    if (!data_lists)
00744      {
00745         printf("Creating new data lists.\n");
00746         data_lists = _data_new();
00747         if (!data_lists)
00748           {
00749              ret = -2;
00750              goto end;
00751           }
00752      }
00753 
00754    if (argc > 3)
00755      {
00756         if (strcmp(argv[3], "union") == 0)
00757           {
00758              if (argc > 4)
00759                {
00760                   int type = atoi(argv[4]);
00761                   Example_Union *un;
00762 
00763                   if (type < EET_STRUCT1 || type > EET_BASIC_STRING)
00764                     {
00765                        fprintf(stderr,
00766                                "ERROR: invalid type parameter (%s).\n",
00767                                argv[4]);
00768                        goto cont;
00769                     }
00770 
00771                   switch (type)
00772                     {
00773                      case 1:
00774                        if (argc != 8)
00775                          {
00776                             fprintf(
00777                               stderr, "ERROR: wrong number of parameters"
00778                                       " (%d).\n", argc);
00779                             goto cont;
00780                          }
00781 
00782                        un = _union_1_new(
00783                            argv[5], argv[6], argv[7]);
00784                        if (!un)
00785                          {
00786                             fprintf(
00787                               stderr, "ERROR: could not create the "
00788                                       "requested union.\n");
00789                             goto cont;
00790                          }
00791                        data_lists->union_list =
00792                          eina_list_append(data_lists->union_list, un);
00793                        break;
00794 
00795                      case 2:
00796                        if (argc != 7)
00797                          {
00798                             fprintf(
00799                               stderr, "ERROR: wrong number of parameters"
00800                                       " (%d).\n", argc);
00801                             goto cont;
00802                          }
00803 
00804                        un = _union_2_new(argv[5], argv[6]);
00805                        if (!un)
00806                          {
00807                             fprintf(
00808                               stderr, "ERROR: could not create the "
00809                                       "requested union.\n");
00810                             goto cont;
00811                          }
00812                        data_lists->union_list =
00813                          eina_list_append(data_lists->union_list, un);
00814                        break;
00815 
00816                      case 3:
00817                        if (argc != 6)
00818                          {
00819                             fprintf(
00820                               stderr, "ERROR: wrong number of parameters"
00821                                       " (%d).\n", argc);
00822                             goto cont;
00823                          }
00824 
00825                        un = _union_3_new(argv[5]);
00826                        if (!un)
00827                          {
00828                             fprintf(
00829                               stderr, "ERROR: could not create the "
00830                                       "requested union.\n");
00831                             goto cont;
00832                          }
00833                        data_lists->union_list =
00834                          eina_list_append(data_lists->union_list, un);
00835                        break;
00836 
00837                      case EET_BASIC_FLOAT:
00838                        if (argc != 6)
00839                          {
00840                             fprintf(
00841                               stderr, "ERROR: wrong number of parameters"
00842                                       " (%d).\n", argc);
00843                             goto cont;
00844                          }
00845 
00846                        un = _union_float_new(argv[5]);
00847                        if (!un)
00848                          {
00849                             fprintf(
00850                               stderr, "ERROR: could not create the "
00851                                       "requested union.\n");
00852                             goto cont;
00853                          }
00854                        data_lists->union_list =
00855                          eina_list_append(data_lists->union_list, un);
00856                        break;
00857 
00858                      case EET_BASIC_STRING:
00859                        if (argc != 6)
00860                          {
00861                             fprintf(
00862                               stderr, "ERROR: wrong number of parameters"
00863                                       " (%d).\n", argc);
00864                             goto cont;
00865                          }
00866 
00867                        un = _union_string_new(argv[5]);
00868                        if (!un)
00869                          {
00870                             fprintf(
00871                               stderr, "ERROR: could not create the "
00872                                       "requested union.\n");
00873                             goto cont;
00874                          }
00875                        data_lists->union_list =
00876                          eina_list_append(data_lists->union_list, un);
00877                        break;
00878 
00879                      default:
00880                        fprintf(
00881                          stderr, "ERROR: bad type of of struct passed\n");
00882                        goto cont;
00883                     }
00884                }
00885              else
00886                fprintf(stderr,
00887                        "ERROR: wrong number of parameters (%d).\n",
00888                        argc);
00889           }
00890         else if (strcmp(argv[3], "variant") == 0)
00891           {
00892              if (argc > 4)
00893                {
00894                   int type = atoi(argv[4]);
00895                   Example_Variant *va;
00896 
00897                   if (type < EET_STRUCT1 || type > EET_STRUCT3)
00898                     {
00899                        fprintf(stderr,
00900                                "ERROR: invalid type parameter (%s).\n",
00901                                argv[4]);
00902                        goto cont;
00903                     }
00904 
00905                   switch (type)
00906                     {
00907                      case 1:
00908                        if (argc != 8)
00909                          {
00910                             fprintf(
00911                               stderr, "ERROR: wrong number of parameters"
00912                                       " (%d).\n", argc);
00913                             goto cont;
00914                          }
00915 
00916                        va = _variant_1_new(
00917                            argv[5], argv[6], argv[7]);
00918                        if (!va)
00919                          {
00920                             fprintf(
00921                               stderr, "ERROR: could not create the "
00922                                       "requested variant.\n");
00923                             goto cont;
00924                          }
00925                        data_lists->variant_list =
00926                          eina_list_append(data_lists->variant_list, va);
00927                        break;
00928 
00929                      case 2:
00930                        if (argc != 7)
00931                          {
00932                             fprintf(
00933                               stderr, "ERROR: wrong number of parameters"
00934                                       " (%d).\n", argc);
00935                             goto cont;
00936                          }
00937 
00938                        va = _variant_2_new(argv[5], argv[6]);
00939                        if (!va)
00940                          {
00941                             fprintf(
00942                               stderr, "ERROR: could not create the "
00943                                       "requested variant.\n");
00944                             goto cont;
00945                          }
00946                        data_lists->variant_list =
00947                          eina_list_append(data_lists->variant_list, va);
00948                        break;
00949 
00950                      case 3:
00951                        if (argc != 6)
00952                          {
00953                             fprintf(
00954                               stderr, "ERROR: wrong number of parameters"
00955                                       " (%d).\n", argc);
00956                             goto cont;
00957                          }
00958 
00959                        va = _variant_3_new(argv[5]);
00960                        if (!va)
00961                          {
00962                             fprintf(
00963                               stderr, "ERROR: could not create the "
00964                                       "requested variant.\n");
00965                             goto cont;
00966                          }
00967                        data_lists->variant_list =
00968                          eina_list_append(data_lists->variant_list, va);
00969                        break;
00970 
00971                      default:
00972                        fprintf(
00973                          stderr, "ERROR: bad type of of struct passed\n");
00974                        goto cont;
00975                     }
00976                }
00977              else
00978                fprintf(stderr,
00979                        "ERROR: wrong number of parameters (%d).\n",
00980                        argc);
00981           }
00982         else
00983           fprintf(stderr, "ERROR: unknown action '%s'\n", argv[3]);
00984      }
00985 
00986 cont:
00987    printf("Cached data:\n");
00988 
00989    printf("\tstats: unions=%u, variants=%u\n",
00990           eina_list_count(data_lists->union_list),
00991           eina_list_count(data_lists->variant_list));
00992 
00993    if (eina_list_count(data_lists->union_list))
00994      {
00995         const Eina_List *l;
00996         const Example_Union *un;
00997         printf("\t  * union list:\n");
00998 
00999         EINA_LIST_FOREACH(data_lists->union_list, l, un)
01000           {
01001              _print_union(un);
01002           }
01003      }
01004 
01005    if (eina_list_count(data_lists->variant_list))
01006      {
01007         const Eina_List *l;
01008         const Example_Variant *un;
01009         printf("\t  * variant list:\n");
01010 
01011         EINA_LIST_FOREACH(data_lists->variant_list, l, un)
01012           {
01013              _print_variant(un);
01014           }
01015      }
01016 
01017    printf("\n");
01018 
01019    if (!_data_save(data_lists, argv[2]))
01020      ret = -3;
01021 
01022    _data_free(data_lists);
01023 
01024 end:
01025    if (_cache_file)
01026      eet_close(_cache_file);
01027    _data_descriptors_shutdown();
01028    eet_shutdown();
01029    eina_shutdown();
01030 
01031    return ret;
01032 } /* main */
01033