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