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
};

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