Tizen Native API  3.0
Nested data example
00001 //Compile with:
00002 // gcc -o eet-data-nested eet-data-nested.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 // The struct that will be loaded and saved.
00013 // note that only the members described in the eet_data_descriptor
00014 // will be automatically handled. The other members will have their
00015 // space reserved and zeroed (as it uses calloc()), but not
00016 // saved or loaded from eet files.
00017 typedef struct
00018 {
00019    unsigned int version; // it is recommended to use versioned configuration!
00020    const char  *name;
00021    int          id;
00022    int          not_saved_value; // example of not saved data inside!
00023    Eina_Bool    enabled;
00024    Eina_List   *subs;
00025 } My_Conf_Type;
00026 
00027 typedef struct
00028 {
00029    const char *server;
00030    int         port;
00031 } My_Conf_Subtype;
00032 
00033 // string that represents the entry in eet file, you might like to have
00034 // different profiles or so in the same file, this is possible with
00035 // different strings
00036 static const char MY_CONF_FILE_ENTRY[] = "config";
00037 
00038 // keep the descriptor static global, so it can be
00039 // shared by different functions (load/save) of this and only this
00040 // file.
00041 static Eet_Data_Descriptor *_my_conf_descriptor;
00042 static Eet_Data_Descriptor *_my_conf_sub_descriptor;
00043 
00044 static void
00045 _my_conf_descriptor_init(void)
00046 {
00047    Eet_Data_Descriptor_Class eddc;
00048 
00049    // The class describe the functions to use to create the type and its
00050    // full allocated size.
00051    //
00052    // Eina types are very convenient, so use them to create the descriptor,
00053    // so we get eina_list,  eina_hash and eina_stringshare automatically!
00054    //
00055    // The STREAM variant is better for configuration files as the values
00056    // will likely change a lot.
00057    //
00058    // The other variant, FILE, is good for caches and things that are just
00059    // appended, but needs to take care when changing strings and files must
00060    // be kept open so mmap()ed strings will be kept alive.
00061    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, My_Conf_Type);
00062    _my_conf_descriptor = eet_data_descriptor_stream_new(&eddc);
00063 
00064    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, My_Conf_Subtype);
00065    _my_conf_sub_descriptor = eet_data_descriptor_stream_new(&eddc);
00066 
00067    // Describe the members to be saved:
00068    // Use a temporary macro so we don't type a lot, also avoid errors:
00069 #define MY_CONF_ADD_BASIC(member, eet_type) \
00070   EET_DATA_DESCRIPTOR_ADD_BASIC             \
00071     (_my_conf_descriptor, My_Conf_Type, # member, member, eet_type)
00072 #define MY_CONF_SUB_ADD_BASIC(member, eet_type) \
00073   EET_DATA_DESCRIPTOR_ADD_BASIC                 \
00074     (_my_conf_sub_descriptor, My_Conf_Subtype, # member, member, eet_type)
00075 
00076    MY_CONF_SUB_ADD_BASIC(server, EET_T_STRING);
00077    MY_CONF_SUB_ADD_BASIC(port, EET_T_INT);
00078 
00079    MY_CONF_ADD_BASIC(version, EET_T_UINT);
00080    MY_CONF_ADD_BASIC(name, EET_T_STRING);
00081    MY_CONF_ADD_BASIC(id, EET_T_INT);
00082    MY_CONF_ADD_BASIC(enabled, EET_T_UCHAR);
00083 
00084    // And add the sub descriptor as a linked list at 'subs' in the main struct
00085    EET_DATA_DESCRIPTOR_ADD_LIST
00086      (_my_conf_descriptor, My_Conf_Type, "subs", subs, _my_conf_sub_descriptor);
00087 
00088 #undef MY_CONF_ADD_BASIC
00089 #undef MY_CONF_SUB_ADD_BASIC
00090 } /* _my_conf_descriptor_init */
00091 
00092 static void
00093 _my_conf_descriptor_shutdown(void)
00094 {
00095    eet_data_descriptor_free(_my_conf_sub_descriptor);
00096    eet_data_descriptor_free(_my_conf_descriptor);
00097 } /* _my_conf_descriptor_shutdown */
00098 
00099 static My_Conf_Type *
00100 _my_conf_new(void)
00101 {
00102    My_Conf_Type *my_conf = calloc(1, sizeof(My_Conf_Type));
00103    My_Conf_Subtype *sub;
00104    if (!my_conf)
00105      {
00106         fprintf(stderr, "ERROR: could not calloc My_Conf_Type\n");
00107         return NULL;
00108      }
00109 
00110    my_conf->version = 0x112233;
00111    my_conf->enabled = EINA_TRUE;
00112 
00113    sub = calloc(1, sizeof(My_Conf_Subtype));
00114    if (sub)
00115      {
00116         sub->server = eina_stringshare_add("my-server.com");
00117         sub->port = 1234;
00118         my_conf->subs = eina_list_append(my_conf->subs, sub);
00119      }
00120 
00121    return my_conf;
00122 } /* _my_conf_new */
00123 
00124 static void
00125 _my_conf_free(My_Conf_Type *my_conf)
00126 {
00127    My_Conf_Subtype *sub;
00128    EINA_LIST_FREE(my_conf->subs, sub)
00129      {
00130         eina_stringshare_del(sub->server);
00131         free(sub);
00132      }
00133 
00134    eina_stringshare_del(my_conf->name);
00135    free(my_conf);
00136 } /* _my_conf_free */
00137 
00138 static My_Conf_Type *
00139 _my_conf_load(const char *filename)
00140 {
00141    My_Conf_Type *my_conf;
00142    Eet_File *ef = eet_open(filename, EET_FILE_MODE_READ);
00143    if (!ef)
00144      {
00145         fprintf(stderr, "ERROR: could not open '%s' for read\n", filename);
00146         return NULL;
00147      }
00148 
00149    my_conf = eet_data_read(ef, _my_conf_descriptor, MY_CONF_FILE_ENTRY);
00150    if (!my_conf)
00151      goto end;
00152 
00153    if (my_conf->version < 0x112233)
00154      {
00155         fprintf(stderr,
00156                 "WARNING: version %#x was too old, upgrading it to %#x\n",
00157                 my_conf->version, 0x112233);
00158 
00159         my_conf->version = 0x112233;
00160         my_conf->enabled = EINA_TRUE;
00161      }
00162 
00163 end:
00164    eet_close(ef);
00165    return my_conf;
00166 } /* _my_conf_load */
00167 
00168 static Eina_Bool
00169 _my_conf_save(const My_Conf_Type *my_conf,
00170               const char         *filename)
00171 {
00172    char tmp[PATH_MAX];
00173    Eet_File *ef;
00174    Eina_Bool ret;
00175    unsigned int i, len;
00176    struct stat st;
00177 
00178    len = eina_strlcpy(tmp, filename, sizeof(tmp));
00179    if (len + 12 >= (int)sizeof(tmp))
00180      {
00181         fprintf(stderr, "ERROR: file name is too big: %s\n", filename);
00182         return EINA_FALSE;
00183      }
00184 
00185    i = 0;
00186    do
00187      {
00188         snprintf(tmp + len, 12, ".%u", i);
00189         i++;
00190      }
00191    while (stat(tmp, &st) == 0);
00192 
00193    ef = eet_open(tmp, EET_FILE_MODE_WRITE);
00194    if (!ef)
00195      {
00196         fprintf(stderr, "ERROR: could not open '%s' for write\n", tmp);
00197         return EINA_FALSE;
00198      }
00199 
00200    ret = eet_data_write
00201        (ef, _my_conf_descriptor, MY_CONF_FILE_ENTRY, my_conf, EINA_TRUE);
00202    eet_close(ef);
00203 
00204    if (ret)
00205      {
00206         unlink(filename);
00207         rename(tmp, filename);
00208      }
00209 
00210    return ret;
00211 } /* _my_conf_save */
00212 
00213 int
00214 main(int   argc,
00215      char *argv[])
00216 {
00217    My_Conf_Type *my_conf;
00218    const My_Conf_Subtype *sub;
00219    const Eina_List *l;
00220    int ret = 0;
00221 
00222    if (argc != 3)
00223      {
00224         fprintf(stderr, "Usage:\n\t%s <input> <output>\n\n", argv[0]);
00225         return -1;
00226      }
00227 
00228    eina_init();
00229    eet_init();
00230    _my_conf_descriptor_init();
00231 
00232    my_conf = _my_conf_load(argv[1]);
00233    if (!my_conf)
00234      {
00235         printf("creating new configuration.\n");
00236         my_conf = _my_conf_new();
00237         if (!my_conf)
00238           {
00239              ret = -2;
00240              goto end;
00241           }
00242      }
00243 
00244    printf("My_Conf_Type:\n"
00245           "\tversion: %#x\n"
00246           "\tname...: '%s'\n"
00247           "\tid.....: %d\n"
00248           "\tenabled: %hhu\n"
00249           "\tsubs...:\n",
00250           my_conf->version,
00251           my_conf->name ? my_conf->name : "",
00252           my_conf->id,
00253           my_conf->enabled);
00254 
00255    EINA_LIST_FOREACH(my_conf->subs, l, sub)
00256      printf("\t\tserver: '%s', port: %d\n",
00257             sub->server ? sub->server : "",
00258             sub->port);
00259 
00260    if (!_my_conf_save(my_conf, argv[2]))
00261      ret = -3;
00262 
00263    _my_conf_free(my_conf);
00264 
00265 end:
00266    _my_conf_descriptor_shutdown();
00267    eet_shutdown();
00268    eina_shutdown();
00269 
00270    return ret;
00271 } /* main */
00272