diff options
Diffstat (limited to 'libraries/eet/src/lib')
-rw-r--r-- | libraries/eet/src/lib/Eet.h | 4156 | ||||
-rw-r--r-- | libraries/eet/src/lib/Eet_private.h | 191 | ||||
-rw-r--r-- | libraries/eet/src/lib/Makefile.am | 162 | ||||
-rw-r--r-- | libraries/eet/src/lib/Makefile.in | 846 | ||||
-rw-r--r-- | libraries/eet/src/lib/eet_cipher.c | 1342 | ||||
-rw-r--r-- | libraries/eet/src/lib/eet_connection.c | 249 | ||||
-rw-r--r-- | libraries/eet/src/lib/eet_data.c | 4999 | ||||
-rw-r--r-- | libraries/eet/src/lib/eet_dictionary.c | 439 | ||||
-rw-r--r-- | libraries/eet/src/lib/eet_image.c | 1820 | ||||
-rw-r--r-- | libraries/eet/src/lib/eet_lib.c | 2648 | ||||
-rw-r--r-- | libraries/eet/src/lib/eet_node.c | 797 | ||||
-rw-r--r-- | libraries/eet/src/lib/eet_utils.c | 36 |
12 files changed, 17685 insertions, 0 deletions
diff --git a/libraries/eet/src/lib/Eet.h b/libraries/eet/src/lib/Eet.h new file mode 100644 index 0000000..8fda1e0 --- /dev/null +++ b/libraries/eet/src/lib/Eet.h | |||
@@ -0,0 +1,4156 @@ | |||
1 | /** | ||
2 | @brief Eet Data Handling Library Public API Calls | ||
3 | |||
4 | These routines are used for Eet Library interaction | ||
5 | |||
6 | @mainpage Eet Library Documentation | ||
7 | |||
8 | @version 1.5.0 | ||
9 | @date 2000-2011 | ||
10 | |||
11 | Please see the @ref authors page for contact details. | ||
12 | |||
13 | @section toc Table of Contents | ||
14 | |||
15 | @li @ref intro | ||
16 | @li @ref example | ||
17 | @li @ref compiling | ||
18 | @li @ref install | ||
19 | @li @ref next_steps | ||
20 | @li @ref intro_example | ||
21 | |||
22 | @section intro What is Eet? | ||
23 | |||
24 | It is a tiny library designed to write an arbitrary set of chunks of data | ||
25 | to a file and optionally compress each chunk (very much like a zip file) | ||
26 | and allow fast random-access reading of the file later on. It does not | ||
27 | do zip as a zip itself has more complexity than is needed, and it was much | ||
28 | simpler to implement this once here. | ||
29 | |||
30 | Eet is extremely fast, small and simple. Eet files can be very small and | ||
31 | highly compressed, making them very optimal for just sending across the | ||
32 | internet without having to archive, compress or decompress and install them. | ||
33 | They allow for lightning-fast random-acess reads once created, making them | ||
34 | perfect for storing data that is written once (or rarely) and read many | ||
35 | times, but the program does not want to have to read it all in at once. | ||
36 | |||
37 | It also can encode and decode data structures in memory, as well as image | ||
38 | data for saving to Eet files or sending across the network to other | ||
39 | machines, or just writing to arbitrary files on the system. All data is | ||
40 | encoded in a platform independent way and can be written and read by any | ||
41 | architecture. | ||
42 | |||
43 | @section example A simple example on using Eet | ||
44 | |||
45 | Here is a simple example on how to use Eet to save a series of strings to a | ||
46 | file and load them again. The advantage of using Eet over just | ||
47 | fprintf() and | ||
48 | fscanf() is that not only can these entries be strings, they need no special | ||
49 | parsing to handle delimiter characters or escaping, they can be binary data, | ||
50 | image data, data structures containing integers, strings, other data | ||
51 | structures, linked lists and much more, without the programmer having to | ||
52 | worry about parsing, and best of all, Eet is very fast. | ||
53 | |||
54 | This is just a very simple example that doesn't show all of the capabilities | ||
55 | of Eet, but it serves to illustrate its simplicity. | ||
56 | |||
57 | @include eet-basic.c | ||
58 | |||
59 | @section compiling How to compile using Eet ? | ||
60 | |||
61 | Eet is a library your application links to. The procedure for this is very | ||
62 | simple. You simply have to compile your application with the appropriate | ||
63 | compiler flags that the @p pkg-config script outputs. For example: | ||
64 | |||
65 | Compiling C or C++ files into object files: | ||
66 | |||
67 | @verbatim | ||
68 | gcc -c -o main.o main.c `pkg-config --cflags eet` | ||
69 | @endverbatim | ||
70 | |||
71 | Linking object files into a binary executable: | ||
72 | |||
73 | @verbatim | ||
74 | gcc -o my_application main.o `pkg-config --libs eet` | ||
75 | @endverbatim | ||
76 | |||
77 | You simply have to make sure that pkg-config is in your shell's PATH (see | ||
78 | the manual page for your appropriate shell) and eet.pc in /usr/lib/pkgconfig | ||
79 | or its path is in the PKG_CONFIG_PATH environment variable. It's that simple | ||
80 | to link and use Eet once you have written your code to use it. | ||
81 | |||
82 | Since the program is linked to Eet, it is now able to use any advertised | ||
83 | API calls to serialize your data. | ||
84 | |||
85 | You should make sure you add any extra compile and link flags to your | ||
86 | compile commands that your application may need as well. The above example | ||
87 | is only guaranteed to make Eet add it's own requirements. | ||
88 | |||
89 | |||
90 | @section install How is it installed? | ||
91 | |||
92 | Simple: | ||
93 | |||
94 | @verbatim | ||
95 | ./configure | ||
96 | make | ||
97 | su - | ||
98 | ... | ||
99 | make install | ||
100 | @endverbatim | ||
101 | |||
102 | @section next_steps Next Steps | ||
103 | |||
104 | After you understood what Eet is and installed it in your system you | ||
105 | should proceed understanding the programming interface. We'd recommend | ||
106 | you to take a while to learn Eina | ||
107 | (http://docs.enlightenment.org/auto/eina/) as it is very convenient | ||
108 | and optimized, and Eet provides integration with it. | ||
109 | |||
110 | Recommended reading: | ||
111 | |||
112 | @li @ref Eet_File_Group to know the basics to open and save files. | ||
113 | @li @ref Eet_Data_Group to know the convenient way to serialize and | ||
114 | parse your data structures automatically. Just create your | ||
115 | descriptors and let Eet do the work for you. | ||
116 | |||
117 | @section intro_example Introductory Examples | ||
118 | |||
119 | @ref Examples | ||
120 | |||
121 | @todo Document data format for images and data structures. | ||
122 | |||
123 | */ | ||
124 | |||
125 | /** | ||
126 | @page authors Authors | ||
127 | @author Carsten Haitzler <raster@@rasterman.com> | ||
128 | @author David Goodlad <dgoodlad@@gmail.com> | ||
129 | @author Cedric Bail <cedric.bail@@free.fr> | ||
130 | @author Arnaud de Turckheim <quarium@@gmail.com> | ||
131 | @author Luis Felipe Strano Moraes <lfelipe@@profusion.mobi> | ||
132 | @author Chidambar Zinnoury <illogict@@online.fr> | ||
133 | @author Vincent Torri <vtorri@@univ-evry.fr> | ||
134 | @author Gustavo Sverzut Barbieri <barbieri@@profusion.mobi> | ||
135 | @author Raphael Kubo da Costa <kubo@@profusion.mobi> | ||
136 | @author Mathieu Taillefumier <mathieu.taillefumier@@free.fr> | ||
137 | @author Albin "Lutin" Tonnerre <albin.tonnerre@@gmail.com> | ||
138 | @author Adam Simpkins <adam@@adamsimpkins.net> | ||
139 | @author Mike Blumenkrantz <michael.blumenkrantz@gmail.com> | ||
140 | |||
141 | Please contact <enlightenment-devel@lists.sourceforge.net> to get in | ||
142 | contact with the developers and maintainers. | ||
143 | */ | ||
144 | |||
145 | #ifndef _EET_H | ||
146 | #define _EET_H | ||
147 | |||
148 | #include <stdlib.h> | ||
149 | #include <stdio.h> | ||
150 | #include <Eina.h> | ||
151 | |||
152 | #ifdef EAPI | ||
153 | # undef EAPI | ||
154 | #endif /* ifdef EAPI */ | ||
155 | |||
156 | #ifdef _WIN32 | ||
157 | # ifdef EFL_EET_BUILD | ||
158 | # ifdef DLL_EXPORT | ||
159 | # define EAPI __declspec(dllexport) | ||
160 | # else /* ifdef DLL_EXPORT */ | ||
161 | # define EAPI | ||
162 | # endif /* ! DLL_EXPORT */ | ||
163 | # else /* ifdef EFL_EET_BUILD */ | ||
164 | # define EAPI __declspec(dllimport) | ||
165 | # endif /* ! EFL_EET_BUILD */ | ||
166 | #else /* ifdef _WIN32 */ | ||
167 | # ifdef __GNUC__ | ||
168 | # if __GNUC__ >= 4 | ||
169 | # define EAPI __attribute__ ((visibility("default"))) | ||
170 | # else /* if __GNUC__ >= 4 */ | ||
171 | # define EAPI | ||
172 | # endif /* if __GNUC__ >= 4 */ | ||
173 | # else /* ifdef __GNUC__ */ | ||
174 | # define EAPI | ||
175 | # endif /* ifdef __GNUC__ */ | ||
176 | #endif /* ! _WIN32 */ | ||
177 | |||
178 | #ifdef __cplusplus | ||
179 | extern "C" { | ||
180 | #endif /* ifdef __cplusplus */ | ||
181 | |||
182 | /** | ||
183 | * @file Eet.h | ||
184 | * @brief The file that provides the eet functions. | ||
185 | * | ||
186 | * This header provides the Eet management functions. | ||
187 | * | ||
188 | */ | ||
189 | |||
190 | #define EET_VERSION_MAJOR 1 | ||
191 | #define EET_VERSION_MINOR 4 | ||
192 | /** | ||
193 | * @typedef Eet_Version | ||
194 | * | ||
195 | * This is the Eet version information structure that can be used at | ||
196 | * runtime to detect which version of eet is being used and adapt | ||
197 | * appropriately as follows for example: | ||
198 | * | ||
199 | * @code | ||
200 | * #if defined(EET_VERSION_MAJOR) && (EET_VERSION_MAJOR >= 1) && defined(EET_VERSION_MINOR) && (EET_VERSION_MINOR > 2) | ||
201 | * printf("Eet version: %i.%i.%i\n", | ||
202 | * eet_version->major, | ||
203 | * eet_version->minor, | ||
204 | * eet_version->micro); | ||
205 | * if (eet_version->revision > 0) | ||
206 | * { | ||
207 | * printf(" Built from SVN revision # %i\n", eet_version->revision); | ||
208 | * } | ||
209 | * #endif | ||
210 | * @endcode | ||
211 | * | ||
212 | * Note the #if check can be dropped if your program refuses to compile or | ||
213 | * work with an Eet version less than 1.3.0. | ||
214 | */ | ||
215 | typedef struct _Eet_Version | ||
216 | { | ||
217 | int major; /** < major (binary or source incompatible changes) */ | ||
218 | int minor; /** < minor (new features, bugfixes, major improvements version) */ | ||
219 | int micro; /** < micro (bugfix, internal improvements, no new features version) */ | ||
220 | int revision; /** < svn revision (0 if a proper rlease or the svn revsion number Eet is built from) */ | ||
221 | } Eet_Version; | ||
222 | |||
223 | EAPI extern Eet_Version *eet_version; | ||
224 | |||
225 | /** | ||
226 | * @defgroup Eet_Group Top level functions | ||
227 | * Functions that affect Eet as a whole. | ||
228 | * | ||
229 | * @{ | ||
230 | */ | ||
231 | |||
232 | /** | ||
233 | * @enum _Eet_Error | ||
234 | * All the error identifiers known by Eet. | ||
235 | */ | ||
236 | typedef enum _Eet_Error | ||
237 | { | ||
238 | EET_ERROR_NONE, /**< No error, it's all fine! */ | ||
239 | EET_ERROR_BAD_OBJECT, /**< Given object or handle is NULL or invalid */ | ||
240 | EET_ERROR_EMPTY, /**< There was nothing to do */ | ||
241 | EET_ERROR_NOT_WRITABLE, /**< Could not write to file or file is #EET_FILE_MODE_READ */ | ||
242 | EET_ERROR_OUT_OF_MEMORY, /**< Could not allocate memory */ | ||
243 | EET_ERROR_WRITE_ERROR, /**< Failed to write data to destination */ | ||
244 | EET_ERROR_WRITE_ERROR_FILE_TOO_BIG, /**< Failed to write file since it is too big */ | ||
245 | EET_ERROR_WRITE_ERROR_IO_ERROR, /**< Failed to write due a generic Input/Output error */ | ||
246 | EET_ERROR_WRITE_ERROR_OUT_OF_SPACE, /**< Failed to write due out of space */ | ||
247 | EET_ERROR_WRITE_ERROR_FILE_CLOSED, /**< Failed to write because file was closed */ | ||
248 | EET_ERROR_MMAP_FAILED, /**< Could not mmap file */ | ||
249 | EET_ERROR_X509_ENCODING_FAILED, /**< Could not encode using X509 */ | ||
250 | EET_ERROR_SIGNATURE_FAILED, /**< Could not validate signature */ | ||
251 | EET_ERROR_INVALID_SIGNATURE, /**< Signature is invalid */ | ||
252 | EET_ERROR_NOT_SIGNED, /**< File or contents are not signed */ | ||
253 | EET_ERROR_NOT_IMPLEMENTED, /**< Function is not implemented */ | ||
254 | EET_ERROR_PRNG_NOT_SEEDED, /**< Could not introduce random seed */ | ||
255 | EET_ERROR_ENCRYPT_FAILED, /**< Could not encrypt contents */ | ||
256 | EET_ERROR_DECRYPT_FAILED /**< Could not decrypt contents */ | ||
257 | } Eet_Error; /**< Eet error identifiers */ | ||
258 | |||
259 | /** | ||
260 | * @} | ||
261 | */ | ||
262 | |||
263 | /** | ||
264 | * Initialize the EET library. | ||
265 | * | ||
266 | * The first time this function is called, it will perform all the internal | ||
267 | * initialization required for the library to function properly and incrememnt | ||
268 | * the initializiation counter. Any subsequent call only increment this counter | ||
269 | * and return its new value, so it's safe to call this function more than once. | ||
270 | * | ||
271 | * @return The new init count. Will be 0 if initialization failed. | ||
272 | * | ||
273 | * @since 1.0.0 | ||
274 | * @ingroup Eet_Group | ||
275 | */ | ||
276 | EAPI int | ||
277 | eet_init(void); | ||
278 | |||
279 | /** | ||
280 | * Shut down the EET library. | ||
281 | * | ||
282 | * If eet_init() was called more than once for the running application, | ||
283 | * eet_shutdown() will decrement the initialization counter and return its | ||
284 | * new value, without doing anything else. When the counter reaches 0, all | ||
285 | * of the internal elements will be shutdown and any memory used freed. | ||
286 | * | ||
287 | * @return The new init count. | ||
288 | * | ||
289 | * @since 1.0.0 | ||
290 | * @ingroup Eet_Group | ||
291 | */ | ||
292 | EAPI int | ||
293 | eet_shutdown(void); | ||
294 | |||
295 | /** | ||
296 | * Clear eet cache | ||
297 | * | ||
298 | * For a faster access to previously accessed data, Eet keeps an internal | ||
299 | * cache of files. These files will be freed automatically only when | ||
300 | * they are unused and the cache gets full, in order based on the last time | ||
301 | * they were used. | ||
302 | * On systems with little memory this may present an unnecessary constraint, | ||
303 | * so eet_clearcache() is available for users to reclaim the memory used by | ||
304 | * files that are no longer needed. Those that were open using | ||
305 | * ::EET_FILE_MODE_WRITE or ::EET_FILE_MODE_READ_WRITE and have modifications, | ||
306 | * will be written down to disk before flushing them from memory. | ||
307 | * | ||
308 | * @since 1.0.0 | ||
309 | * @ingroup Eet_Group | ||
310 | */ | ||
311 | EAPI void | ||
312 | eet_clearcache(void); | ||
313 | |||
314 | /** | ||
315 | * @defgroup Eet_File_Group Eet File Main Functions | ||
316 | * | ||
317 | * Functions to create, destroy and do basic manipulation of | ||
318 | * #Eet_File handles. | ||
319 | * | ||
320 | * This sections explains how to use the most basic Eet functions, which | ||
321 | * are used to work with eet files, read data from them, store it back in or | ||
322 | * take a look at what entries it contains, without making use of the | ||
323 | * serialization capabilities explained in @ref Eet_Data_Group. | ||
324 | * | ||
325 | * The following example will serve as an introduction to most, if not all, | ||
326 | * of these functions. | ||
327 | * | ||
328 | * If you are only using Eet, this is the only header you need to include. | ||
329 | * @dontinclude eet-file.c | ||
330 | * @skipline Eet.h | ||
331 | * | ||
332 | * Now let's create ourselves an eet file to play with. The following function | ||
333 | * shows step by step how to open a file and write some data in it. | ||
334 | * First, we define our file handler and some other things we'll put in it. | ||
335 | * @line static int | ||
336 | * @skip Eet_File | ||
337 | * @until "; | ||
338 | * @skip eet_open | ||
339 | * | ||
340 | * We open a new file in write mode, and if it fails, we just return, since | ||
341 | * there's not much more we can do about it.. | ||
342 | * @until return | ||
343 | * | ||
344 | * Now, we need to write some data in our file. For now, strings will suffice, | ||
345 | * so let's just dump a bunch of them in there. | ||
346 | * @until } | ||
347 | * | ||
348 | * As you can see, we copied a string into our static buffer, which is a bit | ||
349 | * bigger than the full length of the string, and then told Eet to write it | ||
350 | * into the file, compressed, returning the size of the data written into the | ||
351 | * file. | ||
352 | * This is all to show that Eet treats data as just data. It doesn't matter | ||
353 | * what that data represents (for now), it's all just bytes for it. As running | ||
354 | * the following code will show, we took a string of around 30 bytes and put it | ||
355 | * in a buffer of 1024 bytes, but the returned size won't be any of those. | ||
356 | * @until printf | ||
357 | * | ||
358 | * Next, we copy into our buffer our set of strings, including their null | ||
359 | * terminators and write them into the file. No error checking for the sake | ||
360 | * of brevitiy. And a call to eet_sync() to make sure all out data is | ||
361 | * properly written down to disk, even though we haven't yet closed the file. | ||
362 | * @until eet_sync | ||
363 | * | ||
364 | * One more write, this time our large array of binary data and... well, I | ||
365 | * couldn't come up with a valid use of the last set of strings we stored, | ||
366 | * so let's take it out from the file with eet_delete(). | ||
367 | * @until eet_delete | ||
368 | * | ||
369 | * Finally, we close the file, saving any changes back to disk and return. | ||
370 | * Notice how, if there's any error closing the file or saving its contents, | ||
371 | * the return value from the function will be a false one, which later on | ||
372 | * will make the program exit with an error code. | ||
373 | * @until return | ||
374 | * | ||
375 | * Moving onto our main function, we will open the same file and read it back. | ||
376 | * Trivial, but it'll show how we can do so in more than one way. We'll skip | ||
377 | * the variable declarations, as they aren't very different from what we've | ||
378 | * seen already. | ||
379 | * | ||
380 | * We start from the beginning by initializing Eet so things in general work. | ||
381 | * Forgetting to do so will result in weird results or crashes when calling | ||
382 | * any eet function, so if you experience something like that, the first thing | ||
383 | * to look at is whether eet_init() is missing. | ||
384 | * Then we call our @p create_eet_file function, described above, to make | ||
385 | * sure we have something to work with. If the function fails it will return | ||
386 | * 0 and we just exit, since nothing from here onwards will work anyway. | ||
387 | * @skip eet_init | ||
388 | * @until return | ||
389 | * | ||
390 | * Let's take a look now at what entries our file has. For this, we use | ||
391 | * eet_list(), which will return a list of strings, each being the name of | ||
392 | * one entry. Since we skipped before, it may be worth noting that @p list | ||
393 | * is declared as a @p char **. | ||
394 | * The @p num parameter will, of course, have the number of entries contained | ||
395 | * in our file. | ||
396 | * If everything's fine, we'll get our list and print it to the screen, and | ||
397 | * once done with it, we free the list. That's just the list, not its contents, | ||
398 | * as they are internal strings used by Eet and trying to free them will surely | ||
399 | * break things. | ||
400 | * @until } | ||
401 | * | ||
402 | * Reading back plain data is simple. Just a call to eet_read() with the file | ||
403 | * to read from, and the name of the entry we are interested in. We get back | ||
404 | * our data and the passed @p size parameter will contain the size of it. If | ||
405 | * the data was stored compressed, it will decompressed first. | ||
406 | * @until } | ||
407 | * | ||
408 | * Another simple read for the set of strings from before, except those were | ||
409 | * deleted, so we should get a NULL return and continue normally. | ||
410 | * @until } | ||
411 | * | ||
412 | * Finally, we'll get our binary data in the same way we got the strings. Once | ||
413 | * again, it makes no difference for Eet what the data is, it's up to us to | ||
414 | * know how to handle it. | ||
415 | * @until { | ||
416 | * | ||
417 | * Now some cheating, we know that this data is an Eet file because, well... | ||
418 | * we just know it. So we are going to open it and take a look at its insides. | ||
419 | * For this, eet_open() won't work, as it needs to have a file on disk to read | ||
420 | * from and all we have is some data in RAM. | ||
421 | * | ||
422 | * So how do we do? One way would be to create a normal file and write down | ||
423 | * our data, then open it with eet_open(). Another, faster and more efficient | ||
424 | * if all we want to do is read the file, is to use eet_memopen_read(). | ||
425 | * @until memopen | ||
426 | * | ||
427 | * As you can see, the size we got from our previous read was put to good use | ||
428 | * this time. Unlike the first one where all we had were strings, the size | ||
429 | * of the data read only serves to demonstrate that we are reading back the | ||
430 | * entire size of our original @p buf variable. | ||
431 | * | ||
432 | * A little peeking to see how many entries the file has and to make an | ||
433 | * example of eet_num_entries() to get that number when we don't care about | ||
434 | * their names. | ||
435 | * @until printf | ||
436 | * | ||
437 | * More cheating follows. Just like we knew this was an Eet file, we also know | ||
438 | * what key to read from, and ontop of that we know that the data in it is not | ||
439 | * compressed. | ||
440 | * Knowing all this allows us to take some shortcuts. | ||
441 | * @until read_direct | ||
442 | * | ||
443 | * That's a direct print of our data, whatever that data is. We don't want | ||
444 | * to worry about having to free it later, so we just used eet_direct_read() | ||
445 | * to tell Eet to gives a pointer to the internal data in the file, without | ||
446 | * duplicating it. Since we said that data was not compressed, we shouldn't | ||
447 | * worry about printing garbage to the screen (and yes, we also know the data | ||
448 | * is yet another string). | ||
449 | * We also don't care about the size of the data as it was stored in the file, | ||
450 | * so we passed NULL as the size parameter. | ||
451 | * One very important note about this, however, is that we don't care about | ||
452 | * the size parameter because the data in the file contains the null | ||
453 | * terminator for the string. So when using Eet to store strings this way, | ||
454 | * it's very important to consider whether you will keep that final null | ||
455 | * byte, or to always get the size read and do the necessary checks and copies. | ||
456 | * It's up to the user and the particular use cases to decide how this will | ||
457 | * be done. | ||
458 | * | ||
459 | * With everything done, close this second file and free the data used to open | ||
460 | * it. And this is important, we can't free that data until we are done with | ||
461 | * the file, as Eet is using it. When opening with eet_memopen_read(), the data | ||
462 | * passed to it must be available for as long as the the file is open. | ||
463 | * @until } | ||
464 | * | ||
465 | * Finally, we close the first file, shutdown all internal resources used by | ||
466 | * Eet and leave our main function, thus terminating our program. | ||
467 | * @until return | ||
468 | * | ||
469 | * You can look at the full code of the example @ref eet-file.c "here". | ||
470 | * @{ | ||
471 | */ | ||
472 | |||
473 | /** | ||
474 | * @enum _Eet_File_Mode | ||
475 | * Modes that a file can be opened. | ||
476 | */ | ||
477 | typedef enum _Eet_File_Mode | ||
478 | { | ||
479 | EET_FILE_MODE_INVALID = -1, | ||
480 | EET_FILE_MODE_READ, /**< File is read-only. */ | ||
481 | EET_FILE_MODE_WRITE, /**< File is write-only. */ | ||
482 | EET_FILE_MODE_READ_WRITE /**< File is for both read and write */ | ||
483 | } Eet_File_Mode; /**< Modes that a file can be opened. */ | ||
484 | |||
485 | /** | ||
486 | * @typedef Eet_File | ||
487 | * Opaque handle that defines an Eet file (or memory). | ||
488 | * | ||
489 | * This handle will be returned by the functions eet_open() and | ||
490 | * eet_memopen_read() and is used by every other function that affects the | ||
491 | * file in any way. When you are done with it, call eet_close() to clsoe it | ||
492 | * and, if the file was open for writing, write down to disk any changes made | ||
493 | * to it. | ||
494 | * | ||
495 | * @see eet_open() | ||
496 | * @see eet_memopen_read() | ||
497 | * @see eet_close() | ||
498 | */ | ||
499 | typedef struct _Eet_File Eet_File; | ||
500 | |||
501 | /** | ||
502 | * @typedef Eet_Dictionary | ||
503 | * Opaque handle that defines a file-backed (mmaped) dictionary of strings. | ||
504 | */ | ||
505 | typedef struct _Eet_Dictionary Eet_Dictionary; | ||
506 | |||
507 | /** | ||
508 | * @} | ||
509 | */ | ||
510 | |||
511 | /** | ||
512 | * Open an eet file on disk, and returns a handle to it. | ||
513 | * @param file The file path to the eet file. eg: @c "/tmp/file.eet". | ||
514 | * @param mode The mode for opening. Either #EET_FILE_MODE_READ, | ||
515 | * #EET_FILE_MODE_WRITE or #EET_FILE_MODE_READ_WRITE. | ||
516 | * @return An opened eet file handle. | ||
517 | * @ingroup Eet_File_Group | ||
518 | * | ||
519 | * This function will open an exiting eet file for reading, and build | ||
520 | * the directory table in memory and return a handle to the file, if it | ||
521 | * exists and can be read, and no memory errors occur on the way, otherwise | ||
522 | * NULL will be returned. | ||
523 | * | ||
524 | * It will also open an eet file for writing. This will, if successful, | ||
525 | * delete the original file and replace it with a new empty file, till | ||
526 | * the eet file handle is closed or flushed. If it cannot be opened for | ||
527 | * writing or a memory error occurs, NULL is returned. | ||
528 | * | ||
529 | * You can also open the file for read/write. If you then write a key that | ||
530 | * does not exist it will be created, if the key exists it will be replaced | ||
531 | * by the new data. | ||
532 | * | ||
533 | * If the same file is opened multiple times, then the same file handle will | ||
534 | * be returned as eet maintains an internal list of all currently open | ||
535 | * files. Note that it considers files opened for read only and those opened | ||
536 | * for read/write and write only as 2 separate sets. Those that do not write | ||
537 | * to the file and those that do. Eet will allow 2 handles to the same file | ||
538 | * if they are in the 2 separate lists/groups. That means opening a file for | ||
539 | * read only looks in the read only set, and returns a handle to that file | ||
540 | * handle and increments its reference count. If you open a file for read/write | ||
541 | * or write only it looks in the write set and returns a handle after | ||
542 | * incrementing the reference count. You need to close an eet file handle | ||
543 | * as many times as it has been opened to maintain correct reference counts. | ||
544 | * Files whose modified timestamp or size do not match those of the existing | ||
545 | * referenced file handles will not be returned and a new handle will be | ||
546 | * returned instead. | ||
547 | * | ||
548 | * @since 1.0.0 | ||
549 | */ | ||
550 | EAPI Eet_File * | ||
551 | eet_open(const char *file, | ||
552 | Eet_File_Mode mode); | ||
553 | |||
554 | /** | ||
555 | * Open an eet file directly from a memory location. The data is not copied, | ||
556 | * so you must keep it around as long as the eet file is open. There is | ||
557 | * currently no cache for this kind of Eet_File, so it's reopened every time | ||
558 | * you use eet_memopen_read. | ||
559 | * Files opened this way will always be in read-only mode. | ||
560 | * | ||
561 | * @since 1.1.0 | ||
562 | * @ingroup Eet_File_Group | ||
563 | */ | ||
564 | EAPI Eet_File * | ||
565 | eet_memopen_read(const void *data, | ||
566 | size_t size); | ||
567 | |||
568 | /** | ||
569 | * Get the mode an Eet_File was opened with. | ||
570 | * @param ef A valid eet file handle. | ||
571 | * @return The mode ef was opened with. | ||
572 | * | ||
573 | * @since 1.0.0 | ||
574 | * @ingroup Eet_File_Group | ||
575 | */ | ||
576 | EAPI Eet_File_Mode | ||
577 | eet_mode_get(Eet_File *ef); | ||
578 | |||
579 | /** | ||
580 | * Close an eet file handle and flush and writes pending. | ||
581 | * @param ef A valid eet file handle. | ||
582 | * | ||
583 | * This function will flush any pending writes to disk if the eet file | ||
584 | * was opened for write, and free all data associated with the file handle | ||
585 | * and file, and close the file. | ||
586 | * | ||
587 | * If the eet file handle is not valid nothing will be done. | ||
588 | * | ||
589 | * @since 1.0.0 | ||
590 | * @ingroup Eet_File_Group | ||
591 | */ | ||
592 | EAPI Eet_Error | ||
593 | eet_close(Eet_File *ef); | ||
594 | |||
595 | /** | ||
596 | * Sync content of an eet file handle, flushing pending writes. | ||
597 | * @param ef A valid eet file handle. | ||
598 | * | ||
599 | * This function will flush any pending writes to disk. The eet file must | ||
600 | * be opened for write. | ||
601 | * | ||
602 | * If the eet file handle is not valid nothing will be done. | ||
603 | * | ||
604 | * @since 1.2.4 | ||
605 | * @ingroup Eet_File_Group | ||
606 | */ | ||
607 | EAPI Eet_Error | ||
608 | eet_sync(Eet_File *ef); | ||
609 | |||
610 | /** | ||
611 | * Return a handle to the shared string dictionary of the Eet file | ||
612 | * @param ef A valid eet file handle. | ||
613 | * @return A handle to the dictionary of the file | ||
614 | * | ||
615 | * This function returns a handle to the dictionary of an Eet file whose | ||
616 | * handle is @p ef, if a dictionary exists. NULL is returned otherwise or | ||
617 | * if the file handle is known to be invalid. | ||
618 | * | ||
619 | * @see eet_dictionary_string_check() to know if given string came | ||
620 | * from the dictionary or it was dynamically allocated using | ||
621 | * the #Eet_Data_Descriptor_Class instructrions. | ||
622 | * | ||
623 | * @since 1.0.0 | ||
624 | * @ingroup Eet_File_Group | ||
625 | */ | ||
626 | EAPI Eet_Dictionary * | ||
627 | eet_dictionary_get(Eet_File *ef); | ||
628 | |||
629 | /** | ||
630 | * Check if a given string comes from a given dictionary | ||
631 | * @param ed A valid dictionary handle | ||
632 | * @param string A valid 0 byte terminated C string | ||
633 | * @return 1 if it is in the dictionary, 0 otherwise | ||
634 | * | ||
635 | * This checks the given dictionary to see if the given string is actually | ||
636 | * inside that dictionary (i.e. comes from it) and returns 1 if it does. | ||
637 | * If the dictionary handle is invalid, the string is NULL or the string is | ||
638 | * not in the dictionary, 0 is returned. | ||
639 | * | ||
640 | * @since 1.0.0 | ||
641 | * @ingroup Eet_File_Group | ||
642 | */ | ||
643 | EAPI int | ||
644 | eet_dictionary_string_check(Eet_Dictionary *ed, | ||
645 | const char *string); | ||
646 | |||
647 | /** | ||
648 | * Read a specified entry from an eet file and return data | ||
649 | * @param ef A valid eet file handle opened for reading. | ||
650 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
651 | * @param size_ret Number of bytes read from entry and returned. | ||
652 | * @return The data stored in that entry in the eet file. | ||
653 | * | ||
654 | * This function finds an entry in the eet file that is stored under the | ||
655 | * name specified, and returns that data, decompressed, if successful. | ||
656 | * NULL is returned if the lookup fails or if memory errors are | ||
657 | * encountered. It is the job of the calling program to call free() on | ||
658 | * the returned data. The number of bytes in the returned data chunk are | ||
659 | * placed in size_ret. | ||
660 | * | ||
661 | * If the eet file handle is not valid NULL is returned and size_ret is | ||
662 | * filled with 0. | ||
663 | * | ||
664 | * @see eet_read_cipher() | ||
665 | * | ||
666 | * @since 1.0.0 | ||
667 | * @ingroup Eet_File_Group | ||
668 | */ | ||
669 | EAPI void * | ||
670 | eet_read(Eet_File *ef, | ||
671 | const char *name, | ||
672 | int *size_ret); | ||
673 | |||
674 | /** | ||
675 | * Read a specified entry from an eet file and return data | ||
676 | * @param ef A valid eet file handle opened for reading. | ||
677 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
678 | * @param size_ret Number of bytes read from entry and returned. | ||
679 | * @return The data stored in that entry in the eet file. | ||
680 | * | ||
681 | * This function finds an entry in the eet file that is stored under the | ||
682 | * name specified, and returns that data if not compressed and successful. | ||
683 | * NULL is returned if the lookup fails or if memory errors are | ||
684 | * encountered or if the data is comrpessed. The calling program must never | ||
685 | * call free() on the returned data. The number of bytes in the returned | ||
686 | * data chunk are placed in size_ret. | ||
687 | * | ||
688 | * If the eet file handle is not valid NULL is returned and size_ret is | ||
689 | * filled with 0. | ||
690 | * | ||
691 | * @since 1.0.0 | ||
692 | * @ingroup Eet_File_Group | ||
693 | */ | ||
694 | EAPI const void * | ||
695 | eet_read_direct(Eet_File *ef, | ||
696 | const char *name, | ||
697 | int *size_ret); | ||
698 | |||
699 | /** | ||
700 | * Write a specified entry to an eet file handle | ||
701 | * @param ef A valid eet file handle opened for writing. | ||
702 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
703 | * @param data Pointer to the data to be stored. | ||
704 | * @param size Length in bytes in the data to be stored. | ||
705 | * @param compress Compression flags (1 == compress, 0 = don't compress). | ||
706 | * @return bytes written on successful write, 0 on failure. | ||
707 | * | ||
708 | * This function will write the specified chunk of data to the eet file | ||
709 | * and return greater than 0 on success. 0 will be returned on failure. | ||
710 | * | ||
711 | * The eet file handle must be a valid file handle for an eet file opened | ||
712 | * for writing. If it is not, 0 will be returned and no action will be | ||
713 | * performed. | ||
714 | * | ||
715 | * Name, and data must not be NULL, and size must be > 0. If these | ||
716 | * conditions are not met, 0 will be returned. | ||
717 | * | ||
718 | * The data will be copied (and optionally compressed) in ram, pending | ||
719 | * a flush to disk (it will stay in ram till the eet file handle is | ||
720 | * closed though). | ||
721 | * | ||
722 | * @see eet_write_cipher() | ||
723 | * | ||
724 | * @since 1.0.0 | ||
725 | * @ingroup Eet_File_Group | ||
726 | */ | ||
727 | EAPI int | ||
728 | eet_write(Eet_File *ef, | ||
729 | const char *name, | ||
730 | const void *data, | ||
731 | int size, | ||
732 | int compress); | ||
733 | |||
734 | /** | ||
735 | * Delete a specified entry from an Eet file being written or re-written | ||
736 | * @param ef A valid eet file handle opened for writing. | ||
737 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
738 | * @return Success or failure of the delete. | ||
739 | * | ||
740 | * This function will delete the specified chunk of data from the eet file | ||
741 | * and return greater than 0 on success. 0 will be returned on failure. | ||
742 | * | ||
743 | * The eet file handle must be a valid file handle for an eet file opened | ||
744 | * for writing. If it is not, 0 will be returned and no action will be | ||
745 | * performed. | ||
746 | * | ||
747 | * Name, must not be NULL, otherwise 0 will be returned. | ||
748 | * | ||
749 | * @since 1.0.0 | ||
750 | * @ingroup Eet_File_Group | ||
751 | */ | ||
752 | EAPI int | ||
753 | eet_delete(Eet_File *ef, | ||
754 | const char *name); | ||
755 | |||
756 | /** | ||
757 | * Alias a specific section to another one. Destination may exist or not, | ||
758 | * no check are done. | ||
759 | * @param ef A valid eet file handle opened for writing. | ||
760 | * @param name Name of the new entry. eg: "/base/file_i_want". | ||
761 | * @param destination Actual source of the aliased entry eg: "/base/the_real_stuff_i_want". | ||
762 | * @param compress Compression flags (1 == compress, 0 = don't compress). | ||
763 | * @return EINA_TRUE on success, EINA_FALSE on failure. | ||
764 | * | ||
765 | * Name and Destination must not be NULL, otherwise EINA_FALSE will be returned. | ||
766 | * The equivalent of this would be calling 'ln -s destination name' | ||
767 | * | ||
768 | * @since 1.3.3 | ||
769 | * @ingroup Eet_File_Group | ||
770 | */ | ||
771 | EAPI Eina_Bool | ||
772 | eet_alias(Eet_File *ef, | ||
773 | const char *name, | ||
774 | const char *destination, | ||
775 | int compress); | ||
776 | |||
777 | /** | ||
778 | * Retrieve the destination name of an alias | ||
779 | * @param ef A valid eet file handle opened for writing | ||
780 | * @param name Name of the entry. eg: "/base/file_i_want" | ||
781 | * @return Destination of the alias. eg: "/base/the_real_stuff_i_want", NULL on failure | ||
782 | * | ||
783 | * Name must not be NULL, otherwise NULL will be returned. | ||
784 | * | ||
785 | * @since 1.5 | ||
786 | * @ingroup Eet_File_Group | ||
787 | */ | ||
788 | EAPI const char * | ||
789 | eet_alias_get(Eet_File *ef, | ||
790 | const char *name); | ||
791 | |||
792 | /** | ||
793 | * List all entries in eet file matching shell glob. | ||
794 | * @param ef A valid eet file handle. | ||
795 | * @param glob A shell glob to match against. | ||
796 | * @param count_ret Number of entries found to match. | ||
797 | * @return Pointer to an array of strings. | ||
798 | * | ||
799 | * This function will list all entries in the eet file matching the | ||
800 | * supplied shell glob and return an allocated list of their names, if | ||
801 | * there are any, and if no memory errors occur. | ||
802 | * | ||
803 | * The eet file handle must be valid and glob must not be NULL, or NULL | ||
804 | * will be returned and count_ret will be filled with 0. | ||
805 | * | ||
806 | * The calling program must call free() on the array returned, but NOT | ||
807 | * on the string pointers in the array. They are taken as read-only | ||
808 | * internals from the eet file handle. They are only valid as long as | ||
809 | * the file handle is not closed. When it is closed those pointers in the | ||
810 | * array are now not valid and should not be used. | ||
811 | * | ||
812 | * On success the array returned will have a list of string pointers | ||
813 | * that are the names of the entries that matched, and count_ret will have | ||
814 | * the number of entries in this array placed in it. | ||
815 | * | ||
816 | * Hint: an easy way to list all entries in an eet file is to use a glob | ||
817 | * value of "*". | ||
818 | * | ||
819 | * @since 1.0.0 | ||
820 | * @ingroup Eet_File_Group | ||
821 | */ | ||
822 | EAPI char ** | ||
823 | eet_list(Eet_File *ef, | ||
824 | const char *glob, | ||
825 | int *count_ret); | ||
826 | |||
827 | /** | ||
828 | * Return the number of entries in the specified eet file. | ||
829 | * @param ef A valid eet file handle. | ||
830 | * @return Number of entries in ef or -1 if the number of entries | ||
831 | * cannot be read due to open mode restrictions. | ||
832 | * | ||
833 | * @since 1.0.0 | ||
834 | * @ingroup Eet_File_Group | ||
835 | */ | ||
836 | EAPI int | ||
837 | eet_num_entries(Eet_File *ef); | ||
838 | |||
839 | /** | ||
840 | * @defgroup Eet_File_Cipher_Group Eet File Ciphered Main Functions | ||
841 | * | ||
842 | * Most of the @ref Eet_File_Group have alternative versions that | ||
843 | * accounts for ciphers to protect their content. | ||
844 | * | ||
845 | * @see @ref Eet_Cipher_Group | ||
846 | * | ||
847 | * @ingroup Eet_File_Group | ||
848 | */ | ||
849 | |||
850 | /** | ||
851 | * Read a specified entry from an eet file and return data using a cipher. | ||
852 | * @param ef A valid eet file handle opened for reading. | ||
853 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
854 | * @param size_ret Number of bytes read from entry and returned. | ||
855 | * @param cipher_key The key to use as cipher. | ||
856 | * @return The data stored in that entry in the eet file. | ||
857 | * | ||
858 | * This function finds an entry in the eet file that is stored under the | ||
859 | * name specified, and returns that data, decompressed, if successful. | ||
860 | * NULL is returned if the lookup fails or if memory errors are | ||
861 | * encountered. It is the job of the calling program to call free() on | ||
862 | * the returned data. The number of bytes in the returned data chunk are | ||
863 | * placed in size_ret. | ||
864 | * | ||
865 | * If the eet file handle is not valid NULL is returned and size_ret is | ||
866 | * filled with 0. | ||
867 | * | ||
868 | * @see eet_read() | ||
869 | * | ||
870 | * @since 1.0.0 | ||
871 | * @ingroup Eet_File_Cipher_Group | ||
872 | */ | ||
873 | EAPI void * | ||
874 | eet_read_cipher(Eet_File *ef, | ||
875 | const char *name, | ||
876 | int *size_ret, | ||
877 | const char *cipher_key); | ||
878 | |||
879 | /** | ||
880 | * Write a specified entry to an eet file handle using a cipher. | ||
881 | * @param ef A valid eet file handle opened for writing. | ||
882 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
883 | * @param data Pointer to the data to be stored. | ||
884 | * @param size Length in bytes in the data to be stored. | ||
885 | * @param compress Compression flags (1 == compress, 0 = don't compress). | ||
886 | * @param cipher_key The key to use as cipher. | ||
887 | * @return bytes written on successful write, 0 on failure. | ||
888 | * | ||
889 | * This function will write the specified chunk of data to the eet file | ||
890 | * and return greater than 0 on success. 0 will be returned on failure. | ||
891 | * | ||
892 | * The eet file handle must be a valid file handle for an eet file opened | ||
893 | * for writing. If it is not, 0 will be returned and no action will be | ||
894 | * performed. | ||
895 | * | ||
896 | * Name, and data must not be NULL, and size must be > 0. If these | ||
897 | * conditions are not met, 0 will be returned. | ||
898 | * | ||
899 | * The data will be copied (and optionally compressed) in ram, pending | ||
900 | * a flush to disk (it will stay in ram till the eet file handle is | ||
901 | * closed though). | ||
902 | * | ||
903 | * @see eet_write() | ||
904 | * | ||
905 | * @since 1.0.0 | ||
906 | * @ingroup Eet_File_Cipher_Group | ||
907 | */ | ||
908 | EAPI int | ||
909 | eet_write_cipher(Eet_File *ef, | ||
910 | const char *name, | ||
911 | const void *data, | ||
912 | int size, | ||
913 | int compress, | ||
914 | const char *cipher_key); | ||
915 | |||
916 | /** | ||
917 | * @defgroup Eet_File_Image_Group Image Store and Load | ||
918 | * | ||
919 | * Eet efficiently stores and loads images, including alpha | ||
920 | * channels and lossy compressions. | ||
921 | * | ||
922 | * Eet can handle both lossy compression with different levels of quality and | ||
923 | * non-lossy compression with different compression levels. It's also possible, | ||
924 | * given an image data, to only read its header to get the image information | ||
925 | * without decoding the entire content for it. | ||
926 | * | ||
927 | * The encode family of functions will take an image raw buffer and its | ||
928 | * parameters and compress it in memory, returning the new buffer. | ||
929 | * Likewise, the decode functions will read from the given location in memory | ||
930 | * and return the uncompressed image. | ||
931 | * | ||
932 | * The read and write functions will, respectively, encode and decode to or | ||
933 | * from an Eet file, under the specified key. | ||
934 | * | ||
935 | * These functions are fairly low level and the same functionality can be | ||
936 | * achieved using Evas and Edje, making it much easier to work with images | ||
937 | * as well as not needing to worry about things like scaling them. | ||
938 | */ | ||
939 | |||
940 | /** | ||
941 | * Read just the header data for an image and dont decode the pixels. | ||
942 | * @param ef A valid eet file handle opened for reading. | ||
943 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
944 | * @param w A pointer to the unsigned int to hold the width in pixels. | ||
945 | * @param h A pointer to the unsigned int to hold the height in pixels. | ||
946 | * @param alpha A pointer to the int to hold the alpha flag. | ||
947 | * @param compress A pointer to the int to hold the compression amount. | ||
948 | * @param quality A pointer to the int to hold the quality amount. | ||
949 | * @param lossy A pointer to the int to hold the lossiness flag. | ||
950 | * @return 1 on successful decode, 0 otherwise | ||
951 | * | ||
952 | * Reads and decodes the image header data stored under the given key and | ||
953 | * Eet file. | ||
954 | * | ||
955 | * The information decoded is placed in each of the parameters, which must be | ||
956 | * provided. The width and height, measured in pixels, will be stored under | ||
957 | * the variables pointed by @p w and @p h, respectively. If the read or | ||
958 | * decode of the header fails, this values will be 0. The @p alpha parameter | ||
959 | * will be 1 or 0, denoting if the alpha channel of the image is used or not. | ||
960 | * If the image was losslessly compressed, the @p compress parameter will hold | ||
961 | * the compression amount used, ranging from 0 to 9 and @p lossy will be 0. | ||
962 | * In the case of lossy compression, @p lossy will be 1, and the compression | ||
963 | * quality will be placed under @p quality, with a value ranging from 0 to 100. | ||
964 | * | ||
965 | * @see eet_data_image_header_decode() | ||
966 | * @see eet_data_image_header_read_cipher() | ||
967 | * | ||
968 | * @since 1.0.0 | ||
969 | * @ingroup Eet_File_Image_Group | ||
970 | */ | ||
971 | EAPI int | ||
972 | eet_data_image_header_read(Eet_File *ef, | ||
973 | const char *name, | ||
974 | unsigned int *w, | ||
975 | unsigned int *h, | ||
976 | int *alpha, | ||
977 | int *compress, | ||
978 | int *quality, | ||
979 | int *lossy); | ||
980 | |||
981 | /** | ||
982 | * Read image data from the named key in the eet file. | ||
983 | * @param ef A valid eet file handle opened for reading. | ||
984 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
985 | * @param w A pointer to the unsigned int to hold the width in pixels. | ||
986 | * @param h A pointer to the unsigned int to hold the height in pixels. | ||
987 | * @param alpha A pointer to the int to hold the alpha flag. | ||
988 | * @param compress A pointer to the int to hold the compression amount. | ||
989 | * @param quality A pointer to the int to hold the quality amount. | ||
990 | * @param lossy A pointer to the int to hold the lossiness flag. | ||
991 | * @return The image pixel data decoded | ||
992 | * | ||
993 | * Reads and decodes the image stored in the given Eet file under the named | ||
994 | * key. | ||
995 | * | ||
996 | * The returned pixel data is a linear array of pixels starting from the | ||
997 | * top-left of the image, scanning row by row from left to right. Each pile | ||
998 | * is a 32bit value, with the high byte being the alpha channel, the next being | ||
999 | * red, then green, and the low byte being blue. | ||
1000 | * | ||
1001 | * The rest of the parameters are the same as in eet_data_image_header_read(). | ||
1002 | * | ||
1003 | * On success the function returns a pointer to the image data decoded. The | ||
1004 | * calling application is responsible for calling free() on the image data | ||
1005 | * when it is done with it. On failure NULL is returned and the parameter | ||
1006 | * values may not contain any sensible data. | ||
1007 | * | ||
1008 | * @see eet_data_image_header_read() | ||
1009 | * @see eet_data_image_decode() | ||
1010 | * @see eet_data_image_read_cipher() | ||
1011 | * @see eet_data_image_read_to_surface() | ||
1012 | * | ||
1013 | * @since 1.0.0 | ||
1014 | * @ingroup Eet_File_Image_Group | ||
1015 | */ | ||
1016 | EAPI void * | ||
1017 | eet_data_image_read(Eet_File *ef, | ||
1018 | const char *name, | ||
1019 | unsigned int *w, | ||
1020 | unsigned int *h, | ||
1021 | int *alpha, | ||
1022 | int *compress, | ||
1023 | int *quality, | ||
1024 | int *lossy); | ||
1025 | |||
1026 | /** | ||
1027 | * Read image data from the named key in the eet file and store it in the given buffer. | ||
1028 | * @param ef A valid eet file handle opened for reading. | ||
1029 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
1030 | * @param src_x The starting x coordinate from where to dump the stream. | ||
1031 | * @param src_y The starting y coordinate from where to dump the stream. | ||
1032 | * @param d A pointer to the pixel surface. | ||
1033 | * @param w The expected width in pixels of the pixel surface to decode. | ||
1034 | * @param h The expected height in pixels of the pixel surface to decode. | ||
1035 | * @param row_stride The length of a pixels line in the destination surface. | ||
1036 | * @param alpha A pointer to the int to hold the alpha flag. | ||
1037 | * @param compress A pointer to the int to hold the compression amount. | ||
1038 | * @param quality A pointer to the int to hold the quality amount. | ||
1039 | * @param lossy A pointer to the int to hold the lossiness flag. | ||
1040 | * @return 1 on success, 0 otherwise. | ||
1041 | * | ||
1042 | * Reads and decodes the image stored in the given Eet file, placing the | ||
1043 | * resulting pixel data in the buffer pointed by the user. | ||
1044 | * | ||
1045 | * Like eet_data_image_read(), it takes the image data stored under the | ||
1046 | * @p name key in the @p ef file, but instead of returning a new buffer with | ||
1047 | * the pixel data, it places the result in the buffer pointed by @p d, which | ||
1048 | * must be provided by the user and of sufficient size to hold the requested | ||
1049 | * portion of the image. | ||
1050 | * | ||
1051 | * The @p src_x and @p src_y parameters indicate the top-left corner of the | ||
1052 | * section of the image to decode. These have to be higher or equal than 0 and | ||
1053 | * less than the respective total width and height of the image. The width | ||
1054 | * and height of the section of the image to decode are given in @p w and @p h | ||
1055 | * and also can't be higher than the total width and height of the image. | ||
1056 | * | ||
1057 | * The @p row_stride parameter indicates the length in bytes of each line in | ||
1058 | * the destination buffer and it has to be at least @p w * 4. | ||
1059 | * | ||
1060 | * All the other parameters are the same as in eet_data_image_read(). | ||
1061 | * | ||
1062 | * On success the function returns 1, and 0 on failure. On failure the | ||
1063 | * parameter values may not contain any sensible data. | ||
1064 | * | ||
1065 | * @see eet_data_image_read() | ||
1066 | * @see eet_data_image_decode() | ||
1067 | * @see eet_data_image_decode_to_surface() | ||
1068 | * @see eet_data_image_read_to_surface_cipher() | ||
1069 | * | ||
1070 | * @since 1.0.2 | ||
1071 | * @ingroup Eet_File_Image_Group | ||
1072 | */ | ||
1073 | EAPI int | ||
1074 | eet_data_image_read_to_surface(Eet_File *ef, | ||
1075 | const char *name, | ||
1076 | unsigned int src_x, | ||
1077 | unsigned int src_y, | ||
1078 | unsigned int *d, | ||
1079 | unsigned int w, | ||
1080 | unsigned int h, | ||
1081 | unsigned int row_stride, | ||
1082 | int *alpha, | ||
1083 | int *compress, | ||
1084 | int *quality, | ||
1085 | int *lossy); | ||
1086 | |||
1087 | /** | ||
1088 | * Write image data to the named key in an eet file. | ||
1089 | * @param ef A valid eet file handle opened for writing. | ||
1090 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
1091 | * @param data A pointer to the image pixel data. | ||
1092 | * @param w The width of the image in pixels. | ||
1093 | * @param h The height of the image in pixels. | ||
1094 | * @param alpha The alpha channel flag. | ||
1095 | * @param compress The compression amount. | ||
1096 | * @param quality The quality encoding amount. | ||
1097 | * @param lossy The lossiness flag. | ||
1098 | * @return Success if the data was encoded and written or not. | ||
1099 | * | ||
1100 | * This function takes image pixel data and encodes it in an eet file | ||
1101 | * stored under the supplied name key, and returns how many bytes were | ||
1102 | * actually written to encode the image data. | ||
1103 | * | ||
1104 | * The data expected is the same format as returned by eet_data_image_read. | ||
1105 | * If this is not the case weird things may happen. Width and height must | ||
1106 | * be between 1 and 8000 pixels. The alpha flags can be 0 or 1 (0 meaning | ||
1107 | * the alpha values are not useful and 1 meaning they are). Compress can | ||
1108 | * be from 0 to 9 (0 meaning no compression, 9 meaning full compression). | ||
1109 | * This is only used if the image is not lossily encoded. Quality is used on | ||
1110 | * lossy compression and should be a value from 0 to 100. The lossy flag | ||
1111 | * can be 0 or 1. 0 means encode losslessly and 1 means to encode with | ||
1112 | * image quality loss (but then have a much smaller encoding). | ||
1113 | * | ||
1114 | * On success this function returns the number of bytes that were required | ||
1115 | * to encode the image data, or on failure it returns 0. | ||
1116 | * | ||
1117 | * @see eet_data_image_read() | ||
1118 | * @see eet_data_image_encode() | ||
1119 | * @see eet_data_image_write_cipher() | ||
1120 | * | ||
1121 | * @since 1.0.0 | ||
1122 | * @ingroup Eet_File_Image_Group | ||
1123 | */ | ||
1124 | EAPI int | ||
1125 | eet_data_image_write(Eet_File *ef, | ||
1126 | const char *name, | ||
1127 | const void *data, | ||
1128 | unsigned int w, | ||
1129 | unsigned int h, | ||
1130 | int alpha, | ||
1131 | int compress, | ||
1132 | int quality, | ||
1133 | int lossy); | ||
1134 | |||
1135 | /** | ||
1136 | * Decode Image data header only to get information. | ||
1137 | * @param data The encoded pixel data. | ||
1138 | * @param size The size, in bytes, of the encoded pixel data. | ||
1139 | * @param w A pointer to the unsigned int to hold the width in pixels. | ||
1140 | * @param h A pointer to the unsigned int to hold the height in pixels. | ||
1141 | * @param alpha A pointer to the int to hold the alpha flag. | ||
1142 | * @param compress A pointer to the int to hold the compression amount. | ||
1143 | * @param quality A pointer to the int to hold the quality amount. | ||
1144 | * @param lossy A pointer to the int to hold the lossiness flag. | ||
1145 | * @return 1 on success, 0 on failure. | ||
1146 | * | ||
1147 | * This function works exactly like eet_data_image_header_read(), but instead | ||
1148 | * of reading from an Eet file, it takes the buffer of size @p size pointed | ||
1149 | * by @p data, which must be a valid Eet encoded image. | ||
1150 | * | ||
1151 | * On success the function returns 1 indicating the header was read and | ||
1152 | * decoded properly, or 0 on failure. | ||
1153 | * | ||
1154 | * @see eet_data_image_header_read() | ||
1155 | * @see eet_data_image_header_decode_cipher() | ||
1156 | * | ||
1157 | * @since 1.0.0 | ||
1158 | * @ingroup Eet_File_Image_Group | ||
1159 | */ | ||
1160 | EAPI int | ||
1161 | eet_data_image_header_decode(const void *data, | ||
1162 | int size, | ||
1163 | unsigned int *w, | ||
1164 | unsigned int *h, | ||
1165 | int *alpha, | ||
1166 | int *compress, | ||
1167 | int *quality, | ||
1168 | int *lossy); | ||
1169 | |||
1170 | /** | ||
1171 | * Decode Image data into pixel data. | ||
1172 | * @param data The encoded pixel data. | ||
1173 | * @param size The size, in bytes, of the encoded pixel data. | ||
1174 | * @param w A pointer to the unsigned int to hold the width in pixels. | ||
1175 | * @param h A pointer to the unsigned int to hold the height in pixels. | ||
1176 | * @param alpha A pointer to the int to hold the alpha flag. | ||
1177 | * @param compress A pointer to the int to hold the compression amount. | ||
1178 | * @param quality A pointer to the int to hold the quality amount. | ||
1179 | * @param lossy A pointer to the int to hold the lossiness flag. | ||
1180 | * @return The image pixel data decoded | ||
1181 | * | ||
1182 | * This function takes encoded pixel data and decodes it into raw RGBA | ||
1183 | * pixels on success. | ||
1184 | * | ||
1185 | * It works exactly like eet_data_image_read(), but it takes the encoded | ||
1186 | * data in the @p data buffer of size @p size, instead of reading from a file. | ||
1187 | * All the others parameters are also the same. | ||
1188 | * | ||
1189 | * On success the function returns a pointer to the image data decoded. The | ||
1190 | * calling application is responsible for calling free() on the image data | ||
1191 | * when it is done with it. On failure NULL is returned and the parameter | ||
1192 | * values may not contain any sensible data. | ||
1193 | * | ||
1194 | * @see eet_data_image_read() | ||
1195 | * @see eet_data_image_decode_cipher() | ||
1196 | * | ||
1197 | * @since 1.0.0 | ||
1198 | * @ingroup Eet_File_Image_Group | ||
1199 | */ | ||
1200 | EAPI void * | ||
1201 | eet_data_image_decode(const void *data, | ||
1202 | int size, | ||
1203 | unsigned int *w, | ||
1204 | unsigned int *h, | ||
1205 | int *alpha, | ||
1206 | int *compress, | ||
1207 | int *quality, | ||
1208 | int *lossy); | ||
1209 | |||
1210 | /** | ||
1211 | * Decode Image data into pixel data and stores in the given buffer. | ||
1212 | * @param data The encoded pixel data. | ||
1213 | * @param size The size, in bytes, of the encoded pixel data. | ||
1214 | * @param src_x The starting x coordinate from where to dump the stream. | ||
1215 | * @param src_y The starting y coordinate from where to dump the stream. | ||
1216 | * @param d A pointer to the pixel surface. | ||
1217 | * @param w The expected width in pixels of the pixel surface to decode. | ||
1218 | * @param h The expected height in pixels of the pixel surface to decode. | ||
1219 | * @param row_stride The length of a pixels line in the destination surface. | ||
1220 | * @param alpha A pointer to the int to hold the alpha flag. | ||
1221 | * @param compress A pointer to the int to hold the compression amount. | ||
1222 | * @param quality A pointer to the int to hold the quality amount. | ||
1223 | * @param lossy A pointer to the int to hold the lossiness flag. | ||
1224 | * @return 1 on success, 0 otherwise. | ||
1225 | * | ||
1226 | * Like eet_data_image_read_to_surface(), but reading the given @p data buffer | ||
1227 | * instead of a file. | ||
1228 | * | ||
1229 | * On success the function returns 1, and 0 on failure. On failure the | ||
1230 | * parameter values may not contain any sensible data. | ||
1231 | * | ||
1232 | * @see eet_data_image_read_to_surface() | ||
1233 | * @see eet_data_image_decode_to_surface_cipher() | ||
1234 | * | ||
1235 | * @since 1.0.2 | ||
1236 | * @ingroup Eet_File_Image_Group | ||
1237 | */ | ||
1238 | EAPI int | ||
1239 | eet_data_image_decode_to_surface(const void *data, | ||
1240 | int size, | ||
1241 | unsigned int src_x, | ||
1242 | unsigned int src_y, | ||
1243 | unsigned int *d, | ||
1244 | unsigned int w, | ||
1245 | unsigned int h, | ||
1246 | unsigned int row_stride, | ||
1247 | int *alpha, | ||
1248 | int *compress, | ||
1249 | int *quality, | ||
1250 | int *lossy); | ||
1251 | |||
1252 | /** | ||
1253 | * Encode image data for storage or transmission. | ||
1254 | * @param data A pointer to the image pixel data. | ||
1255 | * @param size_ret A pointer to an int to hold the size of the returned data. | ||
1256 | * @param w The width of the image in pixels. | ||
1257 | * @param h The height of the image in pixels. | ||
1258 | * @param alpha The alpha channel flag. | ||
1259 | * @param compress The compression amount. | ||
1260 | * @param quality The quality encoding amount. | ||
1261 | * @param lossy The lossiness flag. | ||
1262 | * @return The encoded image data. | ||
1263 | * | ||
1264 | * This function stakes image pixel data and encodes it with compression and | ||
1265 | * possible loss of quality (as a trade off for size) for storage or | ||
1266 | * transmission to another system. | ||
1267 | * | ||
1268 | * It works like eet_data_image_write(), but instead of writing the encoded | ||
1269 | * image into an Eet file, it allocates a new buffer of the size required and | ||
1270 | * returns the encoded data in it. | ||
1271 | * | ||
1272 | * On success this function returns a pointer to the encoded data that you | ||
1273 | * can free with free() when no longer needed. | ||
1274 | * | ||
1275 | * @see eet_data_image_write() | ||
1276 | * @see eet_data_image_read() | ||
1277 | * @see eet_data_image_encode_cipher() | ||
1278 | * | ||
1279 | * @since 1.0.0 | ||
1280 | * @ingroup Eet_File_Image_Group | ||
1281 | */ | ||
1282 | EAPI void * | ||
1283 | eet_data_image_encode(const void *data, | ||
1284 | int *size_ret, | ||
1285 | unsigned int w, | ||
1286 | unsigned int h, | ||
1287 | int alpha, | ||
1288 | int compress, | ||
1289 | int quality, | ||
1290 | int lossy); | ||
1291 | |||
1292 | /** | ||
1293 | * @defgroup Eet_File_Image_Cipher_Group Image Store and Load using a Cipher | ||
1294 | * | ||
1295 | * Most of the @ref Eet_File_Image_Group have alternative versions | ||
1296 | * that accounts for ciphers to protect their content. | ||
1297 | * | ||
1298 | * @see @ref Eet_Cipher_Group | ||
1299 | * | ||
1300 | * @ingroup Eet_File_Image_Group | ||
1301 | */ | ||
1302 | |||
1303 | /** | ||
1304 | * Read just the header data for an image and dont decode the pixels using a cipher. | ||
1305 | * @param ef A valid eet file handle opened for reading. | ||
1306 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
1307 | * @param cipher_key The key to use as cipher. | ||
1308 | * @param w A pointer to the unsigned int to hold the width in pixels. | ||
1309 | * @param h A pointer to the unsigned int to hold the height in pixels. | ||
1310 | * @param alpha A pointer to the int to hold the alpha flag. | ||
1311 | * @param compress A pointer to the int to hold the compression amount. | ||
1312 | * @param quality A pointer to the int to hold the quality amount. | ||
1313 | * @param lossy A pointer to the int to hold the lossiness flag. | ||
1314 | * @return 1 on successful decode, 0 otherwise | ||
1315 | * | ||
1316 | * This function reads an image from an eet file stored under the named | ||
1317 | * key in the eet file and return a pointer to the decompressed pixel data. | ||
1318 | * | ||
1319 | * The other parameters of the image (width, height etc.) are placed into | ||
1320 | * the values pointed to (they must be supplied). The pixel data is a linear | ||
1321 | * array of pixels starting from the top-left of the image scanning row by | ||
1322 | * row from left to right. Each pixel is a 32bit value, with the high byte | ||
1323 | * being the alpha channel, the next being red, then green, and the low byte | ||
1324 | * being blue. The width and height are measured in pixels and will be | ||
1325 | * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes | ||
1326 | * that the alpha channel is not used. 1 denotes that it is significant. | ||
1327 | * Compress is filled with the compression value/amount the image was | ||
1328 | * stored with. The quality value is filled with the quality encoding of | ||
1329 | * the image file (0 - 100). The lossy flags is either 0 or 1 as to if | ||
1330 | * the image was encoded lossily or not. | ||
1331 | * | ||
1332 | * On success the function returns 1 indicating the header was read and | ||
1333 | * decoded properly, or 0 on failure. | ||
1334 | * | ||
1335 | * @see eet_data_image_header_read() | ||
1336 | * | ||
1337 | * @since 1.0.0 | ||
1338 | * @ingroup Eet_File_Image_Cipher_Group | ||
1339 | */ | ||
1340 | EAPI int | ||
1341 | eet_data_image_header_read_cipher(Eet_File *ef, | ||
1342 | const char *name, | ||
1343 | const char *cipher_key, | ||
1344 | unsigned int *w, | ||
1345 | unsigned int *h, | ||
1346 | int *alpha, | ||
1347 | int *compress, | ||
1348 | int *quality, | ||
1349 | int *lossy); | ||
1350 | |||
1351 | /** | ||
1352 | * Read image data from the named key in the eet file using a cipher. | ||
1353 | * @param ef A valid eet file handle opened for reading. | ||
1354 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
1355 | * @param cipher_key The key to use as cipher. | ||
1356 | * @param w A pointer to the unsigned int to hold the width in pixels. | ||
1357 | * @param h A pointer to the unsigned int to hold the height in pixels. | ||
1358 | * @param alpha A pointer to the int to hold the alpha flag. | ||
1359 | * @param compress A pointer to the int to hold the compression amount. | ||
1360 | * @param quality A pointer to the int to hold the quality amount. | ||
1361 | * @param lossy A pointer to the int to hold the lossiness flag. | ||
1362 | * @return The image pixel data decoded | ||
1363 | * | ||
1364 | * This function reads an image from an eet file stored under the named | ||
1365 | * key in the eet file and return a pointer to the decompressed pixel data. | ||
1366 | * | ||
1367 | * The other parameters of the image (width, height etc.) are placed into | ||
1368 | * the values pointed to (they must be supplied). The pixel data is a linear | ||
1369 | * array of pixels starting from the top-left of the image scanning row by | ||
1370 | * row from left to right. Each pixel is a 32bit value, with the high byte | ||
1371 | * being the alpha channel, the next being red, then green, and the low byte | ||
1372 | * being blue. The width and height are measured in pixels and will be | ||
1373 | * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes | ||
1374 | * that the alpha channel is not used. 1 denotes that it is significant. | ||
1375 | * Compress is filled with the compression value/amount the image was | ||
1376 | * stored with. The quality value is filled with the quality encoding of | ||
1377 | * the image file (0 - 100). The lossy flags is either 0 or 1 as to if | ||
1378 | * the image was encoded lossily or not. | ||
1379 | * | ||
1380 | * On success the function returns a pointer to the image data decoded. The | ||
1381 | * calling application is responsible for calling free() on the image data | ||
1382 | * when it is done with it. On failure NULL is returned and the parameter | ||
1383 | * values may not contain any sensible data. | ||
1384 | * | ||
1385 | * @see eet_data_image_read() | ||
1386 | * | ||
1387 | * @since 1.0.0 | ||
1388 | * @ingroup Eet_File_Image_Cipher_Group | ||
1389 | */ | ||
1390 | EAPI void * | ||
1391 | eet_data_image_read_cipher(Eet_File *ef, | ||
1392 | const char *name, | ||
1393 | const char *cipher_key, | ||
1394 | unsigned int *w, | ||
1395 | unsigned int *h, | ||
1396 | int *alpha, | ||
1397 | int *compress, | ||
1398 | int *quality, | ||
1399 | int *lossy); | ||
1400 | |||
1401 | /** | ||
1402 | * Read image data from the named key in the eet file using a cipher. | ||
1403 | * @param ef A valid eet file handle opened for reading. | ||
1404 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
1405 | * @param cipher_key The key to use as cipher. | ||
1406 | * @param src_x The starting x coordinate from where to dump the stream. | ||
1407 | * @param src_y The starting y coordinate from where to dump the stream. | ||
1408 | * @param d A pointer to the pixel surface. | ||
1409 | * @param w The expected width in pixels of the pixel surface to decode. | ||
1410 | * @param h The expected height in pixels of the pixel surface to decode. | ||
1411 | * @param row_stride The length of a pixels line in the destination surface. | ||
1412 | * @param alpha A pointer to the int to hold the alpha flag. | ||
1413 | * @param compress A pointer to the int to hold the compression amount. | ||
1414 | * @param quality A pointer to the int to hold the quality amount. | ||
1415 | * @param lossy A pointer to the int to hold the lossiness flag. | ||
1416 | * @return 1 on success, 0 otherwise. | ||
1417 | * | ||
1418 | * This function reads an image from an eet file stored under the named | ||
1419 | * key in the eet file and return a pointer to the decompressed pixel data. | ||
1420 | * | ||
1421 | * The other parameters of the image (width, height etc.) are placed into | ||
1422 | * the values pointed to (they must be supplied). The pixel data is a linear | ||
1423 | * array of pixels starting from the top-left of the image scanning row by | ||
1424 | * row from left to right. Each pixel is a 32bit value, with the high byte | ||
1425 | * being the alpha channel, the next being red, then green, and the low byte | ||
1426 | * being blue. The width and height are measured in pixels and will be | ||
1427 | * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes | ||
1428 | * that the alpha channel is not used. 1 denotes that it is significant. | ||
1429 | * Compress is filled with the compression value/amount the image was | ||
1430 | * stored with. The quality value is filled with the quality encoding of | ||
1431 | * the image file (0 - 100). The lossy flags is either 0 or 1 as to if | ||
1432 | * the image was encoded lossily or not. | ||
1433 | * | ||
1434 | * On success the function returns 1, and 0 on failure. On failure the | ||
1435 | * parameter values may not contain any sensible data. | ||
1436 | * | ||
1437 | * @see eet_data_image_read_to_surface() | ||
1438 | * | ||
1439 | * @since 1.0.2 | ||
1440 | * @ingroup Eet_File_Image_Cipher_Group | ||
1441 | */ | ||
1442 | EAPI int | ||
1443 | eet_data_image_read_to_surface_cipher(Eet_File *ef, | ||
1444 | const char *name, | ||
1445 | const char *cipher_key, | ||
1446 | unsigned int src_x, | ||
1447 | unsigned int src_y, | ||
1448 | unsigned int *d, | ||
1449 | unsigned int w, | ||
1450 | unsigned int h, | ||
1451 | unsigned int row_stride, | ||
1452 | int *alpha, | ||
1453 | int *compress, | ||
1454 | int *quality, | ||
1455 | int *lossy); | ||
1456 | |||
1457 | /** | ||
1458 | * Write image data to the named key in an eet file using a cipher. | ||
1459 | * @param ef A valid eet file handle opened for writing. | ||
1460 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
1461 | * @param cipher_key The key to use as cipher. | ||
1462 | * @param data A pointer to the image pixel data. | ||
1463 | * @param w The width of the image in pixels. | ||
1464 | * @param h The height of the image in pixels. | ||
1465 | * @param alpha The alpha channel flag. | ||
1466 | * @param compress The compression amount. | ||
1467 | * @param quality The quality encoding amount. | ||
1468 | * @param lossy The lossiness flag. | ||
1469 | * @return Success if the data was encoded and written or not. | ||
1470 | * | ||
1471 | * This function takes image pixel data and encodes it in an eet file | ||
1472 | * stored under the supplied name key, and returns how many bytes were | ||
1473 | * actually written to encode the image data. | ||
1474 | * | ||
1475 | * The data expected is the same format as returned by eet_data_image_read. | ||
1476 | * If this is not the case weird things may happen. Width and height must | ||
1477 | * be between 1 and 8000 pixels. The alpha flags can be 0 or 1 (0 meaning | ||
1478 | * the alpha values are not useful and 1 meaning they are). Compress can | ||
1479 | * be from 0 to 9 (0 meaning no compression, 9 meaning full compression). | ||
1480 | * This is only used if the image is not lossily encoded. Quality is used on | ||
1481 | * lossy compression and should be a value from 0 to 100. The lossy flag | ||
1482 | * can be 0 or 1. 0 means encode losslessly and 1 means to encode with | ||
1483 | * image quality loss (but then have a much smaller encoding). | ||
1484 | * | ||
1485 | * On success this function returns the number of bytes that were required | ||
1486 | * to encode the image data, or on failure it returns 0. | ||
1487 | * | ||
1488 | * @see eet_data_image_write() | ||
1489 | * | ||
1490 | * @since 1.0.0 | ||
1491 | * @ingroup Eet_File_Image_Cipher_Group | ||
1492 | */ | ||
1493 | EAPI int | ||
1494 | eet_data_image_write_cipher(Eet_File *ef, | ||
1495 | const char *name, | ||
1496 | const char *cipher_key, | ||
1497 | const void *data, | ||
1498 | unsigned int w, | ||
1499 | unsigned int h, | ||
1500 | int alpha, | ||
1501 | int compress, | ||
1502 | int quality, | ||
1503 | int lossy); | ||
1504 | |||
1505 | /** | ||
1506 | * Decode Image data header only to get information using a cipher. | ||
1507 | * @param data The encoded pixel data. | ||
1508 | * @param cipher_key The key to use as cipher. | ||
1509 | * @param size The size, in bytes, of the encoded pixel data. | ||
1510 | * @param w A pointer to the unsigned int to hold the width in pixels. | ||
1511 | * @param h A pointer to the unsigned int to hold the height in pixels. | ||
1512 | * @param alpha A pointer to the int to hold the alpha flag. | ||
1513 | * @param compress A pointer to the int to hold the compression amount. | ||
1514 | * @param quality A pointer to the int to hold the quality amount. | ||
1515 | * @param lossy A pointer to the int to hold the lossiness flag. | ||
1516 | * @return 1 on success, 0 on failure. | ||
1517 | * | ||
1518 | * This function takes encoded pixel data and decodes it into raw RGBA | ||
1519 | * pixels on success. | ||
1520 | * | ||
1521 | * The other parameters of the image (width, height etc.) are placed into | ||
1522 | * the values pointed to (they must be supplied). The pixel data is a linear | ||
1523 | * array of pixels starting from the top-left of the image scanning row by | ||
1524 | * row from left to right. Each pixel is a 32bit value, with the high byte | ||
1525 | * being the alpha channel, the next being red, then green, and the low byte | ||
1526 | * being blue. The width and height are measured in pixels and will be | ||
1527 | * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes | ||
1528 | * that the alpha channel is not used. 1 denotes that it is significant. | ||
1529 | * Compress is filled with the compression value/amount the image was | ||
1530 | * stored with. The quality value is filled with the quality encoding of | ||
1531 | * the image file (0 - 100). The lossy flags is either 0 or 1 as to if | ||
1532 | * the image was encoded lossily or not. | ||
1533 | * | ||
1534 | * On success the function returns 1 indicating the header was read and | ||
1535 | * decoded properly, or 0 on failure. | ||
1536 | * | ||
1537 | * @see eet_data_image_header_decode() | ||
1538 | * | ||
1539 | * @since 1.0.0 | ||
1540 | * @ingroup Eet_File_Image_Cipher_Group | ||
1541 | */ | ||
1542 | EAPI int | ||
1543 | eet_data_image_header_decode_cipher(const void *data, | ||
1544 | const char *cipher_key, | ||
1545 | int size, | ||
1546 | unsigned int *w, | ||
1547 | unsigned int *h, | ||
1548 | int *alpha, | ||
1549 | int *compress, | ||
1550 | int *quality, | ||
1551 | int *lossy); | ||
1552 | |||
1553 | /** | ||
1554 | * Decode Image data into pixel data using a cipher. | ||
1555 | * @param data The encoded pixel data. | ||
1556 | * @param cipher_key The key to use as cipher. | ||
1557 | * @param size The size, in bytes, of the encoded pixel data. | ||
1558 | * @param w A pointer to the unsigned int to hold the width in pixels. | ||
1559 | * @param h A pointer to the unsigned int to hold the height in pixels. | ||
1560 | * @param alpha A pointer to the int to hold the alpha flag. | ||
1561 | * @param compress A pointer to the int to hold the compression amount. | ||
1562 | * @param quality A pointer to the int to hold the quality amount. | ||
1563 | * @param lossy A pointer to the int to hold the lossiness flag. | ||
1564 | * @return The image pixel data decoded | ||
1565 | * | ||
1566 | * This function takes encoded pixel data and decodes it into raw RGBA | ||
1567 | * pixels on success. | ||
1568 | * | ||
1569 | * The other parameters of the image (width, height etc.) are placed into | ||
1570 | * the values pointed to (they must be supplied). The pixel data is a linear | ||
1571 | * array of pixels starting from the top-left of the image scanning row by | ||
1572 | * row from left to right. Each pixel is a 32bit value, with the high byte | ||
1573 | * being the alpha channel, the next being red, then green, and the low byte | ||
1574 | * being blue. The width and height are measured in pixels and will be | ||
1575 | * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes | ||
1576 | * that the alpha channel is not used. 1 denotes that it is significant. | ||
1577 | * Compress is filled with the compression value/amount the image was | ||
1578 | * stored with. The quality value is filled with the quality encoding of | ||
1579 | * the image file (0 - 100). The lossy flags is either 0 or 1 as to if | ||
1580 | * the image was encoded lossily or not. | ||
1581 | * | ||
1582 | * On success the function returns a pointer to the image data decoded. The | ||
1583 | * calling application is responsible for calling free() on the image data | ||
1584 | * when it is done with it. On failure NULL is returned and the parameter | ||
1585 | * values may not contain any sensible data. | ||
1586 | * | ||
1587 | * @see eet_data_image_decode() | ||
1588 | * | ||
1589 | * @since 1.0.0 | ||
1590 | * @ingroup Eet_File_Image_Cipher_Group | ||
1591 | */ | ||
1592 | EAPI void * | ||
1593 | eet_data_image_decode_cipher(const void *data, | ||
1594 | const char *cipher_key, | ||
1595 | int size, | ||
1596 | unsigned int *w, | ||
1597 | unsigned int *h, | ||
1598 | int *alpha, | ||
1599 | int *compress, | ||
1600 | int *quality, | ||
1601 | int *lossy); | ||
1602 | |||
1603 | /** | ||
1604 | * Decode Image data into pixel data using a cipher. | ||
1605 | * @param data The encoded pixel data. | ||
1606 | * @param cipher_key The key to use as cipher. | ||
1607 | * @param size The size, in bytes, of the encoded pixel data. | ||
1608 | * @param src_x The starting x coordinate from where to dump the stream. | ||
1609 | * @param src_y The starting y coordinate from where to dump the stream. | ||
1610 | * @param d A pointer to the pixel surface. | ||
1611 | * @param w The expected width in pixels of the pixel surface to decode. | ||
1612 | * @param h The expected height in pixels of the pixel surface to decode. | ||
1613 | * @param row_stride The length of a pixels line in the destination surface. | ||
1614 | * @param alpha A pointer to the int to hold the alpha flag. | ||
1615 | * @param compress A pointer to the int to hold the compression amount. | ||
1616 | * @param quality A pointer to the int to hold the quality amount. | ||
1617 | * @param lossy A pointer to the int to hold the lossiness flag. | ||
1618 | * @return 1 on success, 0 otherwise. | ||
1619 | * | ||
1620 | * This function takes encoded pixel data and decodes it into raw RGBA | ||
1621 | * pixels on success. | ||
1622 | * | ||
1623 | * The other parameters of the image (alpha, compress etc.) are placed into | ||
1624 | * the values pointed to (they must be supplied). The pixel data is a linear | ||
1625 | * array of pixels starting from the top-left of the image scanning row by | ||
1626 | * row from left to right. Each pixel is a 32bit value, with the high byte | ||
1627 | * being the alpha channel, the next being red, then green, and the low byte | ||
1628 | * being blue. The width and height are measured in pixels and will be | ||
1629 | * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes | ||
1630 | * that the alpha channel is not used. 1 denotes that it is significant. | ||
1631 | * Compress is filled with the compression value/amount the image was | ||
1632 | * stored with. The quality value is filled with the quality encoding of | ||
1633 | * the image file (0 - 100). The lossy flags is either 0 or 1 as to if | ||
1634 | * the image was encoded lossily or not. | ||
1635 | * | ||
1636 | * On success the function returns 1, and 0 on failure. On failure the | ||
1637 | * parameter values may not contain any sensible data. | ||
1638 | * | ||
1639 | * @see eet_data_image_decode_to_surface() | ||
1640 | * | ||
1641 | * @since 1.0.2 | ||
1642 | * @ingroup Eet_File_Image_Cipher_Group | ||
1643 | */ | ||
1644 | EAPI int | ||
1645 | eet_data_image_decode_to_surface_cipher(const void *data, | ||
1646 | const char *cipher_key, | ||
1647 | int size, | ||
1648 | unsigned int src_x, | ||
1649 | unsigned int src_y, | ||
1650 | unsigned int *d, | ||
1651 | unsigned int w, | ||
1652 | unsigned int h, | ||
1653 | unsigned int row_stride, | ||
1654 | int *alpha, | ||
1655 | int *compress, | ||
1656 | int *quality, | ||
1657 | int *lossy); | ||
1658 | |||
1659 | /** | ||
1660 | * Encode image data for storage or transmission using a cipher. | ||
1661 | * @param data A pointer to the image pixel data. | ||
1662 | * @param cipher_key The key to use as cipher. | ||
1663 | * @param size_ret A pointer to an int to hold the size of the returned data. | ||
1664 | * @param w The width of the image in pixels. | ||
1665 | * @param h The height of the image in pixels. | ||
1666 | * @param alpha The alpha channel flag. | ||
1667 | * @param compress The compression amount. | ||
1668 | * @param quality The quality encoding amount. | ||
1669 | * @param lossy The lossiness flag. | ||
1670 | * @return The encoded image data. | ||
1671 | * | ||
1672 | * This function stakes image pixel data and encodes it with compression and | ||
1673 | * possible loss of quality (as a trade off for size) for storage or | ||
1674 | * transmission to another system. | ||
1675 | * | ||
1676 | * The data expected is the same format as returned by eet_data_image_read. | ||
1677 | * If this is not the case weird things may happen. Width and height must | ||
1678 | * be between 1 and 8000 pixels. The alpha flags can be 0 or 1 (0 meaning | ||
1679 | * the alpha values are not useful and 1 meaning they are). Compress can | ||
1680 | * be from 0 to 9 (0 meaning no compression, 9 meaning full compression). | ||
1681 | * This is only used if the image is not lossily encoded. Quality is used on | ||
1682 | * lossy compression and should be a value from 0 to 100. The lossy flag | ||
1683 | * can be 0 or 1. 0 means encode losslessly and 1 means to encode with | ||
1684 | * image quality loss (but then have a much smaller encoding). | ||
1685 | * | ||
1686 | * On success this function returns a pointer to the encoded data that you | ||
1687 | * can free with free() when no longer needed. | ||
1688 | * | ||
1689 | * @see eet_data_image_encode() | ||
1690 | * | ||
1691 | * @since 1.0.0 | ||
1692 | * @ingroup Eet_File_Image_Cipher_Group | ||
1693 | */ | ||
1694 | EAPI void * | ||
1695 | eet_data_image_encode_cipher(const void *data, | ||
1696 | const char *cipher_key, | ||
1697 | unsigned int w, | ||
1698 | unsigned int h, | ||
1699 | int alpha, | ||
1700 | int compress, | ||
1701 | int quality, | ||
1702 | int lossy, | ||
1703 | int *size_ret); | ||
1704 | |||
1705 | /** | ||
1706 | * @defgroup Eet_Cipher_Group Cipher, Identity and Protection Mechanisms | ||
1707 | * | ||
1708 | * Eet allows one to protect entries of an #Eet_File | ||
1709 | * individually. This may be used to ensure data was not tampered or | ||
1710 | * that third party does not read your data. | ||
1711 | * | ||
1712 | * @see @ref Eet_File_Cipher_Group | ||
1713 | * @see @ref Eet_File_Image_Cipher_Group | ||
1714 | * | ||
1715 | * @{ | ||
1716 | */ | ||
1717 | |||
1718 | /** | ||
1719 | * @typedef Eet_Key | ||
1720 | * Opaque handle that defines an identity (also known as key) | ||
1721 | * in Eet's cipher system. | ||
1722 | */ | ||
1723 | typedef struct _Eet_Key Eet_Key; | ||
1724 | |||
1725 | /** | ||
1726 | * @} | ||
1727 | */ | ||
1728 | |||
1729 | /** | ||
1730 | * Callback used to request if needed the password of a private key. | ||
1731 | * | ||
1732 | * @param buffer the buffer where to store the password. | ||
1733 | * @param size the maximum password size (size of buffer, including '@\0'). | ||
1734 | * @param rwflag if the buffer is also readable or just writable. | ||
1735 | * @param data currently unused, may contain some context in future. | ||
1736 | * @return 1 on success and password was set to @p buffer, 0 on failure. | ||
1737 | * | ||
1738 | * @since 1.2.0 | ||
1739 | * @ingroup Eet_Cipher_Group | ||
1740 | */ | ||
1741 | typedef int (*Eet_Key_Password_Callback)(char *buffer, int size, int rwflag, void *data); | ||
1742 | |||
1743 | /** | ||
1744 | * Create an Eet_Key needed for signing an eet file. | ||
1745 | * | ||
1746 | * The certificate should provide the public that match the private key. | ||
1747 | * No verification is done to ensure that. | ||
1748 | * | ||
1749 | * @param certificate_file The file where to find the certificate. | ||
1750 | * @param private_key_file The file that contains the private key. | ||
1751 | * @param cb Function to callback if password is required to unlock | ||
1752 | * private key. | ||
1753 | * @return A key handle to use, or @c NULL on failure. | ||
1754 | * | ||
1755 | * @see eet_identity_close() | ||
1756 | * | ||
1757 | * @since 1.2.0 | ||
1758 | * @ingroup Eet_Cipher_Group | ||
1759 | */ | ||
1760 | EAPI Eet_Key * | ||
1761 | eet_identity_open(const char *certificate_file, | ||
1762 | const char *private_key_file, | ||
1763 | Eet_Key_Password_Callback cb); | ||
1764 | |||
1765 | /** | ||
1766 | * Close and release all ressource used by an Eet_Key. An | ||
1767 | * reference counter prevent it from being freed until all file | ||
1768 | * using it are also closed. | ||
1769 | * | ||
1770 | * @param key the key handle to close and free resources. | ||
1771 | * | ||
1772 | * @since 1.2.0 | ||
1773 | * @ingroup Eet_Cipher_Group | ||
1774 | */ | ||
1775 | EAPI void | ||
1776 | eet_identity_close(Eet_Key *key); | ||
1777 | |||
1778 | /** | ||
1779 | * Set a key to sign a file | ||
1780 | * | ||
1781 | * @param ef the file to set the identity. | ||
1782 | * @param key the key handle to set as identity. | ||
1783 | * @return #EET_ERROR_BAD_OBJECT if @p ef is invalid or | ||
1784 | * #EET_ERROR_NONE on success. | ||
1785 | * | ||
1786 | * @since 1.2.0 | ||
1787 | * @ingroup Eet_Cipher_Group | ||
1788 | */ | ||
1789 | EAPI Eet_Error | ||
1790 | eet_identity_set(Eet_File *ef, | ||
1791 | Eet_Key *key); | ||
1792 | |||
1793 | /** | ||
1794 | * Display both private and public key of an Eet_Key. | ||
1795 | * | ||
1796 | * @param key the handle to print. | ||
1797 | * @param out where to print. | ||
1798 | * | ||
1799 | * @since 1.2.0 | ||
1800 | * @ingroup Eet_Cipher_Group | ||
1801 | */ | ||
1802 | EAPI void | ||
1803 | eet_identity_print(Eet_Key *key, | ||
1804 | FILE *out); | ||
1805 | |||
1806 | /** | ||
1807 | * Get the x509 der certificate associated with an Eet_File. Will return NULL | ||
1808 | * if the file is not signed. | ||
1809 | * | ||
1810 | * @param ef The file handle to query. | ||
1811 | * @param der_length The length of returned data, may be @c NULL. | ||
1812 | * @return the x509 certificate or @c NULL on error. | ||
1813 | * | ||
1814 | * @since 1.2.0 | ||
1815 | * @ingroup Eet_Cipher_Group | ||
1816 | */ | ||
1817 | EAPI const void * | ||
1818 | eet_identity_x509(Eet_File *ef, | ||
1819 | int *der_length); | ||
1820 | |||
1821 | /** | ||
1822 | * Get the raw signature associated with an Eet_File. Will return NULL | ||
1823 | * if the file is not signed. | ||
1824 | * | ||
1825 | * @param ef The file handle to query. | ||
1826 | * @param signature_length The length of returned data, may be @c NULL. | ||
1827 | * @return the raw signature or @c NULL on error. | ||
1828 | * | ||
1829 | * @ingroup Eet_Cipher_Group | ||
1830 | */ | ||
1831 | EAPI const void * | ||
1832 | eet_identity_signature(Eet_File *ef, | ||
1833 | int *signature_length); | ||
1834 | |||
1835 | /** | ||
1836 | * Get the SHA1 associated with a file. Could be the one used to | ||
1837 | * sign the data or if the data where not signed, it will be the | ||
1838 | * SHA1 of the file. | ||
1839 | * | ||
1840 | * @param ef The file handle to query. | ||
1841 | * @param sha1_length The length of returned data, may be @c NULL. | ||
1842 | * @return the associated SHA1 or @c NULL on error. | ||
1843 | * | ||
1844 | * @since 1.2.0 | ||
1845 | * @ingroup Eet_Cipher_Group | ||
1846 | */ | ||
1847 | EAPI const void * | ||
1848 | eet_identity_sha1(Eet_File *ef, | ||
1849 | int *sha1_length); | ||
1850 | |||
1851 | /** | ||
1852 | * Display the x509 der certificate to out. | ||
1853 | * | ||
1854 | * @param certificate the x509 certificate to print | ||
1855 | * @param der_length The length the certificate. | ||
1856 | * @param out where to print. | ||
1857 | * | ||
1858 | * @since 1.2.0 | ||
1859 | * @ingroup Eet_Cipher_Group | ||
1860 | */ | ||
1861 | EAPI void | ||
1862 | eet_identity_certificate_print(const unsigned char *certificate, | ||
1863 | int der_length, | ||
1864 | FILE *out); | ||
1865 | |||
1866 | /** | ||
1867 | * @defgroup Eet_Data_Group Eet Data Serialization | ||
1868 | * | ||
1869 | * Convenience functions to serialize and parse complex data | ||
1870 | * structures to binary blobs. | ||
1871 | * | ||
1872 | * While Eet core just handles binary blobs, it is often required | ||
1873 | * to save some structured data of different types, such as | ||
1874 | * strings, integers, lists, hashes and so on. | ||
1875 | * | ||
1876 | * Eet can serialize and then parse data types given some | ||
1877 | * construction instructions. These are defined in two levels: | ||
1878 | * | ||
1879 | * - #Eet_Data_Descriptor_Class to tell generic memory handling, | ||
1880 | * such as the size of the type, how to allocate memory, strings, | ||
1881 | * lists, hashes and so on. | ||
1882 | * | ||
1883 | * - #Eet_Data_Descriptor to tell inside such type, the members and | ||
1884 | * their offsets inside the memory blob, their types and | ||
1885 | * names. These members can be simple types or other | ||
1886 | * #Eet_Data_Descriptor, allowing hierarchical types to be | ||
1887 | * defined. | ||
1888 | * | ||
1889 | * Given that C provides no introspection, this process can be | ||
1890 | * quite cumbersome, so we provide lots of macros and convenience | ||
1891 | * functions to aid creating the types. | ||
1892 | * | ||
1893 | * We make now a quick overview of some of the most commonly used elements | ||
1894 | * of this part of the library. A simple example of a configuration system | ||
1895 | * will work as a somewhat real life example that is still simple enough to | ||
1896 | * follow. | ||
1897 | * Only the relevant sections will be shown here, but you can get the full | ||
1898 | * code @ref eet-data-simple.c "here". | ||
1899 | * | ||
1900 | * Ignoring the included headers, we'll begin by defining our configuration | ||
1901 | * struct. | ||
1902 | * @dontinclude eet-data-simple.c | ||
1903 | * @skip typedef | ||
1904 | * @until } | ||
1905 | * | ||
1906 | * When using Eet, you don't think in matters of what data the program needs | ||
1907 | * to run and which you would like to store. It's all the same and if it makes | ||
1908 | * more sense to keep them together, it's perfectly fine to do so. At the time | ||
1909 | * of telling Eet how your data is comprised you can leave out the things | ||
1910 | * that are runtime only and let Eet take care of the rest for you. | ||
1911 | * | ||
1912 | * The key used to store the config follows, as well as the variable used to | ||
1913 | * store our data descriptor. | ||
1914 | * This last one is very important. It's the one thing that Eet will use to | ||
1915 | * identify your data, both at the time of writing it to the file and when | ||
1916 | * loading from it. | ||
1917 | * @skipline MY_CONF | ||
1918 | * @skipline Eet_Data_Descriptor | ||
1919 | * | ||
1920 | * Now we'll see how to create this descriptor, so Eet knows how to handle | ||
1921 | * our data later on. | ||
1922 | * Begin our function by declaring an Eet_Data_Descriptor_Class, which is | ||
1923 | * used to create the actual descriptor. This class contains the name of | ||
1924 | * our data type, its size and several functions that dictate how Eet should | ||
1925 | * handle memory to allocate the necessary bits to bring our data to life. | ||
1926 | * You, as a user, will very hardly set this class' contents directly. The | ||
1927 | * most common scenario is to use one of the provided macros that set it using | ||
1928 | * the Eina data types, so that's what we'll be doing across all our examples. | ||
1929 | * @skip static void | ||
1930 | * @until eet_data_descriptor_stream_new | ||
1931 | * | ||
1932 | * Now that we have our descriptor, we need to make it describe something. | ||
1933 | * We do so by telling it which members of our struct we want it to know about | ||
1934 | * and their types. | ||
1935 | * The eet_data_descriptor_element_add() function takes care of this, but it's | ||
1936 | * too cumbersome for normal use, so several macros are provided that make | ||
1937 | * it easier to handle. Even with them, however, code can get very repetitive | ||
1938 | * and it's not uncommon to define custom macros using them to save on typing. | ||
1939 | * @skip #define | ||
1940 | * @until } | ||
1941 | * | ||
1942 | * Now our descriptor knows about the parts of our structure that we are | ||
1943 | * interesting in saving. You can see that not all of them are there, yet Eet | ||
1944 | * will find those that need saving and do the right thing. When loading our | ||
1945 | * data, any non-described fields in the structure will be zeroed, so there's | ||
1946 | * no need to worry about garbage memory in them. | ||
1947 | * Refer to the documentation of #EET_DATA_DESCRIPTOR_ADD_BASIC to understand | ||
1948 | * what our macro does. | ||
1949 | * | ||
1950 | * We are done with our descriptor init function and it's proper to have the | ||
1951 | * relevant shutdown. Proper coding guidelines indiciate that all memory | ||
1952 | * allocated should be freed when the program ends, and since you will most | ||
1953 | * likely keep your descriptor around for the life or your application, it's | ||
1954 | * only right to free it at the end. | ||
1955 | * @skip static void | ||
1956 | * @until } | ||
1957 | * | ||
1958 | * Not listed here, but included in the full example are functions to create | ||
1959 | * a blank configuration and free it. The first one will only be used when | ||
1960 | * no file exists to load from, or nothing is found in it, but the latter is | ||
1961 | * used regardless of where our data comes from. Unless you are reading direct | ||
1962 | * data from the Eet file, you will be in charge of freeing anything loaded | ||
1963 | * from it. | ||
1964 | * | ||
1965 | * Now it's time to look at how we can load our config from some file. | ||
1966 | * Begin by opening the Eet file normally. | ||
1967 | * @skip static My_Conf_Type | ||
1968 | * @until } | ||
1969 | * | ||
1970 | * And now we need to read the data from the file and decode it using our | ||
1971 | * descriptor. Fortunately, that's all done in one single step. | ||
1972 | * @until goto | ||
1973 | * | ||
1974 | * And that's it for all Eet cares about. But since we are dealing with a | ||
1975 | * common case, as is save and load of user configurations, the next fragment | ||
1976 | * of code shows why we have a version field in our struct, and how you can | ||
1977 | * use it to load older configuration files and update them as needed. | ||
1978 | * @until } | ||
1979 | * | ||
1980 | * Finally, clsoe the file and return the newly loaded config data. | ||
1981 | * @until } | ||
1982 | * | ||
1983 | * Saving data is just as easy. The full version of the following function | ||
1984 | * includes code to save to a temporary file first, so you can be sure not | ||
1985 | * to lose all your data in the case of a failure mid-writing. You can look | ||
1986 | * at it @ref eet-data-simple.c "here". | ||
1987 | * @skip static Eina_Bool | ||
1988 | * @until { | ||
1989 | * @skipline Eina_Bool ret | ||
1990 | * @skip eet_open | ||
1991 | * @until eet_close | ||
1992 | * @skip return | ||
1993 | * @until } | ||
1994 | * | ||
1995 | * To close, our main function, which doesn't do much. Just take some arguments | ||
1996 | * from the command line with the name of the file to load and another one | ||
1997 | * where to save again. If input file doesn't exist, a new config structure | ||
1998 | * will be created and saved to our output file. | ||
1999 | * @skip int main | ||
2000 | * @until return ret | ||
2001 | * @until } | ||
2002 | * | ||
2003 | * The following is a list of more advanced and detailed examples. | ||
2004 | * @li @ref eet_data_nested_example | ||
2005 | * @li @ref eet_data_file_descriptor | ||
2006 | * @li @ref Example_Eet_Data_File_Descriptor_02 | ||
2007 | * @li @ref Example_Eet_Data_Cipher_Decipher | ||
2008 | */ | ||
2009 | |||
2010 | /** | ||
2011 | * @page eet_data_nested_example Nested structures and Eet Data Descriptors | ||
2012 | * | ||
2013 | * We've seen already a simple example of how to use Eet Data Descriptors | ||
2014 | * to handle our structures, but it didn't show how this works when you | ||
2015 | * have structures inside other structures. | ||
2016 | * | ||
2017 | * Now, there's a very simple case of this, for when you have inline structs | ||
2018 | * to keep your big structure more organized, you don't need anything else | ||
2019 | * besides what @ref eet-data-simple.c "this simple example does". | ||
2020 | * Just use something like @p some_struct.sub_struct.member when adding the | ||
2021 | * member to the descriptor and it will work. | ||
2022 | * | ||
2023 | * For example: | ||
2024 | * @code | ||
2025 | * typedef struct | ||
2026 | * { | ||
2027 | * int a_number; | ||
2028 | * char *a_string; | ||
2029 | * struct { | ||
2030 | * int other_num; | ||
2031 | * int one_more; | ||
2032 | * } sub; | ||
2033 | * } some_struct; | ||
2034 | * | ||
2035 | * void some_function() | ||
2036 | * { | ||
2037 | * ... | ||
2038 | * my_desc = eet_data_descriptor_stream_new(&eddc); | ||
2039 | * EET_DATA_DESCRIPTOR_ADD_BASIC(my_desc, some_struct, "a_number", | ||
2040 | * a_number, EET_T_INT); | ||
2041 | * EET_DATA_DESCRIPTOR_ADD_BASIC(my_desc, some_struct, "a_string", | ||
2042 | * a_string, EET_T_STRING); | ||
2043 | * EET_DATA_DESCRIPTOR_ADD_BASIC(my_desc, some_struct, "sub.other_num", | ||
2044 | * sub.other_num, EET_T_INT); | ||
2045 | * EET_DATA_DESCRIPTOR_ADD_BASIC(my_desc, some_struct, "sub.one_more", | ||
2046 | * sub.one_more", EET_T_INT); | ||
2047 | * ... | ||
2048 | * } | ||
2049 | * @endcode | ||
2050 | * | ||
2051 | * But this is not what we are here for today. When we talk about nested | ||
2052 | * structures, what we really want are things like lists and hashes to be | ||
2053 | * taken into consideration automatically, and all their contents saved and | ||
2054 | * loaded just like ordinary integers and strings are. | ||
2055 | * | ||
2056 | * And of course, Eet can do that, and considering the work it saves you as a | ||
2057 | * programmer, we could say it's even easier to do than handling just integers. | ||
2058 | * | ||
2059 | * Let's begin with our example then, which is not all too different from the | ||
2060 | * simple one introduced earlier. | ||
2061 | * | ||
2062 | * We won't ignore the headers this time to show how easy it is to use Eina | ||
2063 | * data types with Eet, but we'll still skip most of the code that is not | ||
2064 | * pertinent to what we want to show now, but as usual, you can get it full | ||
2065 | * by follwing @ref eet-data-nested.c "this link". | ||
2066 | * | ||
2067 | * @dontinclude eet-data-nested.c | ||
2068 | * @skipline Eina.h | ||
2069 | * @skipline Eet.h | ||
2070 | * @skip typedef struct | ||
2071 | * @until } My_Conf_Subtype | ||
2072 | * | ||
2073 | * Extremely similar to our previous example. Just a new struct in there, and | ||
2074 | * a pointer to a list in the one we already had. Handling a list of subtypes | ||
2075 | * is easy on our program, but now we'll see what Eet needs to work with them | ||
2076 | * (Hint: it's easy too). | ||
2077 | * @skip _my_conf_descriptor | ||
2078 | * @until _my_conf_sub_descriptor | ||
2079 | * | ||
2080 | * Since we have two structures now, it's only natural that we'll need two | ||
2081 | * descriptors. One for each, which will be defined exactly as before. | ||
2082 | * @skip static void | ||
2083 | * @until eddc | ||
2084 | * @skip EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET | ||
2085 | * @until _my_conf_sub_descriptor | ||
2086 | * | ||
2087 | * We create our descriptors, each for one type, and as before, we are going to | ||
2088 | * use a simple macro to set their contents, to save on typing. | ||
2089 | * @skip #define | ||
2090 | * @until EET_T_UCHAR | ||
2091 | * | ||
2092 | * So far, nothing new. We have our descriptors and we know already how to | ||
2093 | * save them separately. But what we want is to link them together, and even | ||
2094 | * more so, we want our main type to hold a list of more than one of the new | ||
2095 | * sub type. So how do we do that? | ||
2096 | * | ||
2097 | * Simple enough, we tell Eet that our main descriptor will hold a list, of | ||
2098 | * which each node will point to some type described by our new descriptor. | ||
2099 | * @skip EET_DATA_DESCRIPTOR_ADD_LIST | ||
2100 | * @until _my_conf_sub_descriptor | ||
2101 | * | ||
2102 | * And that's all. We are closing the function now so as to not leave dangling | ||
2103 | * curly braces, but there's nothing more to show in this example. Only other | ||
2104 | * additions are the necessary code to free our new data, but you can see it | ||
2105 | * in the full code listing. | ||
2106 | * @until } | ||
2107 | */ | ||
2108 | |||
2109 | /** | ||
2110 | * @page eet_data_file_descriptor Advanced use of Eet Data Descriptors | ||
2111 | * | ||
2112 | * A real life example is usually the best way to see how things are used, | ||
2113 | * but they also involve a lot more code than what needs to be shown, so | ||
2114 | * instead of going that way, we'll be borrowing some pieces from one in | ||
2115 | * the following example. It's been slightly modified from the original | ||
2116 | * source to show more of the varied ways in which Eet can handle our data. | ||
2117 | * | ||
2118 | * @ref eet-data-file_descriptor_01.c "This example" shows a cache of user | ||
2119 | * accounts and messages received, and it's a bit more interactive than | ||
2120 | * previous examples. | ||
2121 | * | ||
2122 | * Let's begin by looking at the structures we'll be using. First we have | ||
2123 | * one to define the messages the user receives and one for the one he posts. | ||
2124 | * Straight forward and nothing new here. | ||
2125 | * @dontinclude eet-data-file_descriptor_01.c | ||
2126 | * @skip typedef | ||
2127 | * @until My_Post | ||
2128 | * | ||
2129 | * One more to declare the account itself. This one will contain a list of | ||
2130 | * all messages received, and the posts we make ourselves will be kept in an | ||
2131 | * array. No special reason other than to show how to use arrays with Eet. | ||
2132 | * @until My_Account | ||
2133 | * | ||
2134 | * Finally, the main structure to hold our cache of accounts. We'll be looking | ||
2135 | * for these accounts by their names, so let's keep them in a hash, using | ||
2136 | * that name as the key. | ||
2137 | * @until My_Cache | ||
2138 | * | ||
2139 | * As explained before, we need one descriptor for each struct we want Eet | ||
2140 | * to handle, but this time we also want to keep around our Eet file and its | ||
2141 | * string dictionary. You will see why in a moment. | ||
2142 | * @skip Eet_Data_Descriptor | ||
2143 | * @until _my_post_descriptor | ||
2144 | * @skip Eet_File | ||
2145 | * @until Eet_Dictionary | ||
2146 | * | ||
2147 | * The differences begin now. They aren't much, but we'll be creating our | ||
2148 | * descriptors differently. Things can be added to our cache, but we won't | ||
2149 | * be modifying the current contents, so we can consider the data read from | ||
2150 | * it to be read-only, and thus allow Eet to save time and memory by not | ||
2151 | * duplicating thins unnecessary. | ||
2152 | * @skip static void | ||
2153 | * @until _my_post_descriptor | ||
2154 | * | ||
2155 | * As the comment in the code explains, we are asking Eet to give us strings | ||
2156 | * directly from the mapped file, which avoids having to load it in memory | ||
2157 | * and data duplication. | ||
2158 | * Of course, there are things to take into account when doing things this | ||
2159 | * way, and they will be mentioned as we encounter those special cases. | ||
2160 | * | ||
2161 | * Next comes the actual description of our data, just like we did in the | ||
2162 | * previous examples. | ||
2163 | * @skip #define | ||
2164 | * @until #undef | ||
2165 | * @until #define | ||
2166 | * @until #undef | ||
2167 | * | ||
2168 | * And the account struct's description doesn't add much new, but it's worth | ||
2169 | * commenting on it. | ||
2170 | * @skip #define | ||
2171 | * @until _my_post_descriptor | ||
2172 | * | ||
2173 | * How to add a list we've seen before, but now we are also adding an array. | ||
2174 | * There's nothing really special about it, but it's important to note that | ||
2175 | * the EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY is used to add arrays of variable | ||
2176 | * length to a descriptor. That is, arrays just like the one we defined. | ||
2177 | * Since there's no way in C to know how long they are, we need to keep | ||
2178 | * track of the count ourselves and Eet needs to know how to do so as well. | ||
2179 | * That's what the @p posts_count member of our struct is for. When adding | ||
2180 | * our array member, this macro will look for another variable in the struct | ||
2181 | * named just like the array, but with @p _count attached to the end. | ||
2182 | * When saving our data, Eet will know how many elements the array contains | ||
2183 | * by looking into this count variable. When loading back from a file, this | ||
2184 | * variable will be set to the right number of elements. | ||
2185 | * | ||
2186 | * Another option for arrays is to use EET_DATA_DESCRIPTOR_ADD_ARRAY, which | ||
2187 | * takes care of fixed sized arrays. | ||
2188 | * For example, let's suppose that we want to keep track of only the last | ||
2189 | * ten posts the user sent, and we declare our account struct as follows | ||
2190 | * @code | ||
2191 | * typedef struct | ||
2192 | * { | ||
2193 | * unsigned int id; | ||
2194 | * const char *name; | ||
2195 | * Eina_List *messages; | ||
2196 | * My_Post posts[10]; | ||
2197 | * } My_Account; | ||
2198 | * @endcode | ||
2199 | * Then we would add the array to our descriptor with | ||
2200 | * @code | ||
2201 | * EET_DATA_DESCRIPTOR_ADD_ARRAY(_my_account_descriptor, My_Account, "posts", | ||
2202 | * posts, _my_post_descriptor); | ||
2203 | * @endcode | ||
2204 | * | ||
2205 | * Notice how this time we don't have a @p posts_count variable in our struct. | ||
2206 | * We could have it for the program to keep track of how many posts the | ||
2207 | * array actually contains, but Eet no longer needs it. Being defined that | ||
2208 | * way the array is already taking up all the memory needed for the ten | ||
2209 | * elements, and it is possible in C to determine how much it is in code. | ||
2210 | * When saving our data, Eet will just dump the entire memory blob into the | ||
2211 | * file, regardless of how much of it is really used. So it's important to | ||
2212 | * take into consideration this kind of things when defining your data types. | ||
2213 | * Each has its uses, its advantages and disadvantages and it's up to you | ||
2214 | * to decide which to use. | ||
2215 | * | ||
2216 | * Now, going back to our example, we have to finish adding our data to the | ||
2217 | * descriptors. We are only missing the main one for the cache, which | ||
2218 | * contains our hash of accounts. | ||
2219 | * Unless you are using your own hash functions when setting the descriptor | ||
2220 | * class, always use hashes with string type keys. | ||
2221 | * @skip #define | ||
2222 | * @until } | ||
2223 | * | ||
2224 | * If you remember, we told Eet not to duplicate memory when possible at the | ||
2225 | * time of loading back our data. But this doesn't mean everything will be | ||
2226 | * loaded straight from disk and we don't have to worry about freeing it. | ||
2227 | * Data in the Eet file is compressed and encoded, so it still needs to be | ||
2228 | * decoded and memory will be allocated to convert it back into something we | ||
2229 | * can use. We also need to take care of anything we add in the current | ||
2230 | * instance of the program. | ||
2231 | * To summarize, any string we get from Eet is likely to be a pointer to the | ||
2232 | * internal dictionary, and trying to free it will, in the best case, crash | ||
2233 | * our application right away. | ||
2234 | * | ||
2235 | * So how do we know if we have to free a string? We check if it's part of | ||
2236 | * the dictionary, and if it's not there we can be sure it's safe to get | ||
2237 | * rid of it. | ||
2238 | * @skip static void | ||
2239 | * @skip } | ||
2240 | * @skip static void | ||
2241 | * @until } | ||
2242 | * | ||
2243 | * See how this is used when adding a new message to our cache. | ||
2244 | * @skip static My_Message | ||
2245 | * @until return msg | ||
2246 | * @until free(msg) | ||
2247 | * @until } | ||
2248 | * | ||
2249 | * Skipping all the utility functions used by our program (remember you can | ||
2250 | * look at the full example @ref eet-data-file_descriptor_01.c "here") we get to | ||
2251 | * our cache loading code. Nothing out of the ordinary at first, just the | ||
2252 | * same old open file, read data using our main descriptor to decode it | ||
2253 | * into something we can use and check version of loaded data and if it doesn't | ||
2254 | * match, do something accordingly. | ||
2255 | * @skip static My_Cache | ||
2256 | * @until } | ||
2257 | * @until } | ||
2258 | * @until } | ||
2259 | * | ||
2260 | * Then comes the interesting part. Remember how we kept two more global | ||
2261 | * variables with our descriptors? One of them we already used to check if | ||
2262 | * it was right to free a string or not, but we didn't know where it came from. | ||
2263 | * Loading our data straight from the mmapped file means that we can't close | ||
2264 | * it until we are done using it, so we need to keep its handler around until | ||
2265 | * then. It also means that any changes done to the file can, and will, | ||
2266 | * invalidate all our pointers to the file backed data, so if we add something | ||
2267 | * and save the file, we need to reload our cache. | ||
2268 | * | ||
2269 | * Thus our load function checks if we had an open file, if there is it gets | ||
2270 | * closed and our variable is updated to the new handler. Then we get the | ||
2271 | * string dictionary we use to check if a string is part of it or not. | ||
2272 | * Updating any references to the cache data is up you as a programmer to | ||
2273 | * handle properly, there's nothing Eet can do in this situation. | ||
2274 | * @until } | ||
2275 | * | ||
2276 | * The save function doesn't have anything new, and all that's left after it | ||
2277 | * is the main program, which doesn't really have anything of interest within | ||
2278 | * the scope of what we are learning. | ||
2279 | */ | ||
2280 | |||
2281 | /** | ||
2282 | * @addtogroup Eet_Data_Group | ||
2283 | * @{ | ||
2284 | */ | ||
2285 | #define EET_T_UNKNOW 0 /**< Unknown data encoding type */ | ||
2286 | #define EET_T_CHAR 1 /**< Data type: char */ | ||
2287 | #define EET_T_SHORT 2 /**< Data type: short */ | ||
2288 | #define EET_T_INT 3 /**< Data type: int */ | ||
2289 | #define EET_T_LONG_LONG 4 /**< Data type: long long */ | ||
2290 | #define EET_T_FLOAT 5 /**< Data type: float */ | ||
2291 | #define EET_T_DOUBLE 6 /**< Data type: double */ | ||
2292 | #define EET_T_UCHAR 7 /**< Data type: unsigned char */ | ||
2293 | #define EET_T_USHORT 8 /**< Data type: unsigned short */ | ||
2294 | #define EET_T_UINT 9 /**< Data type: unsigned int */ | ||
2295 | #define EET_T_ULONG_LONG 10 /**< Data type: unsigned long long */ | ||
2296 | #define EET_T_STRING 11 /**< Data type: char * */ | ||
2297 | #define EET_T_INLINED_STRING 12 /**< Data type: char * (but compressed inside the resulting eet) */ | ||
2298 | #define EET_T_NULL 13 /**< Data type: (void *) (only use it if you know why) */ | ||
2299 | #define EET_T_F32P32 14 /**< Data type: fixed point 32.32 */ | ||
2300 | #define EET_T_F16P16 15 /**< Data type: fixed point 16.16 */ | ||
2301 | #define EET_T_F8P24 16 /**< Data type: fixed point 8.24 */ | ||
2302 | #define EET_T_LAST 18 /**< Last data type */ | ||
2303 | |||
2304 | #define EET_G_UNKNOWN 100 /**< Unknown group data encoding type */ | ||
2305 | #define EET_G_ARRAY 101 /**< Fixed size array group type */ | ||
2306 | #define EET_G_VAR_ARRAY 102 /**< Variable size array group type */ | ||
2307 | #define EET_G_LIST 103 /**< Linked list group type */ | ||
2308 | #define EET_G_HASH 104 /**< Hash table group type */ | ||
2309 | #define EET_G_UNION 105 /**< Union group type */ | ||
2310 | #define EET_G_VARIANT 106 /**< Selectable subtype group */ | ||
2311 | #define EET_G_LAST 107 /**< Last group type */ | ||
2312 | |||
2313 | #define EET_I_LIMIT 128 /**< Other type exist but are reserved for internal purpose. */ | ||
2314 | |||
2315 | /** | ||
2316 | * @typedef Eet_Data_Descriptor | ||
2317 | * | ||
2318 | * Opaque handle that have information on a type members. | ||
2319 | * | ||
2320 | * Descriptors are created using an #Eet_Data_Descriptor_Class, and they | ||
2321 | * describe the contents of the structure that will be serialized by Eet. | ||
2322 | * Not all members need be described by it, just those that should be handled | ||
2323 | * by Eet. This way it's possible to have one structure with both data to be | ||
2324 | * saved to a file, like application configuration, and runtime information | ||
2325 | * that would be meaningless to store, but is appropriate to keep together | ||
2326 | * during the program execution. | ||
2327 | * The members are added by means of | ||
2328 | * EET_DATA_DESCRIPTOR_ADD_BASIC(), EET_DATA_DESCRIPTOR_ADD_SUB(), | ||
2329 | * EET_DATA_DESCRIPTOR_ADD_LIST(), EET_DATA_DESCRIPTOR_ADD_HASH() | ||
2330 | * or eet_data_descriptor_element_add(). | ||
2331 | * | ||
2332 | * @see eet_data_descriptor_stream_new() | ||
2333 | * @see eet_data_descriptor_file_new() | ||
2334 | * @see eet_data_descriptor_free() | ||
2335 | */ | ||
2336 | typedef struct _Eet_Data_Descriptor Eet_Data_Descriptor; | ||
2337 | |||
2338 | /** | ||
2339 | * @def EET_DATA_DESCRIPTOR_CLASS_VERSION | ||
2340 | * The version of #Eet_Data_Descriptor_Class at the time of the | ||
2341 | * distribution of the sources. One should define this to its | ||
2342 | * version member so it is compatible with abi changes, or at least | ||
2343 | * will not crash with them. | ||
2344 | */ | ||
2345 | #define EET_DATA_DESCRIPTOR_CLASS_VERSION 4 | ||
2346 | |||
2347 | /** | ||
2348 | * @typedef Eet_Data_Descriptor_Class | ||
2349 | * | ||
2350 | * Instructs Eet about memory management for different needs under | ||
2351 | * serialization and parse process. | ||
2352 | */ | ||
2353 | typedef struct _Eet_Data_Descriptor_Class Eet_Data_Descriptor_Class; | ||
2354 | |||
2355 | typedef int (*Eet_Descriptor_Hash_Foreach_Callback_Callback)(void *h, const char *k, void *dt, void *fdt); | ||
2356 | |||
2357 | typedef void * (*Eet_Descriptor_Mem_Alloc_Callback)(size_t size); | ||
2358 | typedef void (*Eet_Descriptor_Mem_Free_Callback)(void *mem); | ||
2359 | typedef char * (*Eet_Descriptor_Str_Alloc_Callback)(const char *str); | ||
2360 | typedef void (*Eet_Descriptor_Str_Free_Callback)(const char *str); | ||
2361 | typedef void * (*Eet_Descriptor_List_Next_Callback)(void *l); | ||
2362 | typedef void * (*Eet_Descriptor_List_Append_Callback)(void *l, void *d); | ||
2363 | typedef void * (*Eet_Descriptor_List_Data_Callback)(void *l); | ||
2364 | typedef void * (*Eet_Descriptor_List_Free_Callback)(void *l); | ||
2365 | typedef void (*Eet_Descriptor_Hash_Foreach_Callback)(void *h, Eet_Descriptor_Hash_Foreach_Callback_Callback func, void *fdt); | ||
2366 | typedef void * (*Eet_Descriptor_Hash_Add_Callback)(void *h, const char *k, void *d); | ||
2367 | typedef void (*Eet_Descriptor_Hash_Free_Callback)(void *h); | ||
2368 | typedef char * (*Eet_Descriptor_Str_Direct_Alloc_Callback)(const char *str); | ||
2369 | typedef void (*Eet_Descriptor_Str_Direct_Free_Callback)(const char *str); | ||
2370 | typedef const char * (*Eet_Descriptor_Type_Get_Callback)(const void *data, Eina_Bool *unknow); | ||
2371 | typedef Eina_Bool (*Eet_Descriptor_Type_Set_Callback)(const char *type, void *data, Eina_Bool unknow); | ||
2372 | typedef void * (*Eet_Descriptor_Array_Alloc_Callback)(size_t size); | ||
2373 | typedef void (*Eet_Descriptor_Array_Free_Callback)(void *mem); | ||
2374 | /** | ||
2375 | * @struct _Eet_Data_Descriptor_Class | ||
2376 | * | ||
2377 | * Instructs Eet about memory management for different needs under | ||
2378 | * serialization and parse process. | ||
2379 | * | ||
2380 | * The list and hash methods match the Eina API, so for a more detalied | ||
2381 | * reference on them, look at the Eina_List and Eina_Hash documentation, | ||
2382 | * respectively. | ||
2383 | * For the most part these will be used with the standard Eina functions, | ||
2384 | * so using EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET() and | ||
2385 | * EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET() will set up everything | ||
2386 | * accordingly. | ||
2387 | */ | ||
2388 | struct _Eet_Data_Descriptor_Class | ||
2389 | { | ||
2390 | int version; /**< ABI version. Should always be set to #EET_DATA_DESCRIPTOR_CLASS_VERSION */ | ||
2391 | const char *name; /**< Name of the user data type to be serialized */ | ||
2392 | int size; /**< Size in bytes of the user data type to be serialized */ | ||
2393 | struct | ||
2394 | { | ||
2395 | Eet_Descriptor_Mem_Alloc_Callback mem_alloc; /**< how to allocate memory (usually malloc()) */ | ||
2396 | Eet_Descriptor_Mem_Free_Callback mem_free; /**< how to free memory (usually free()) */ | ||
2397 | Eet_Descriptor_Str_Alloc_Callback str_alloc; /**< how to allocate a string */ | ||
2398 | Eet_Descriptor_Str_Free_Callback str_free; /**< how to free a string */ | ||
2399 | Eet_Descriptor_List_Next_Callback list_next; /**< how to iterate to the next element of a list. Receives and should return the list node. */ | ||
2400 | Eet_Descriptor_List_Append_Callback list_append; /**< how to append data @p d to list which head node is @p l */ | ||
2401 | Eet_Descriptor_List_Data_Callback list_data; /**< retrieves the data from node @p l */ | ||
2402 | Eet_Descriptor_List_Free_Callback list_free; /**< free all the nodes from the list which head node is @p l */ | ||
2403 | Eet_Descriptor_Hash_Foreach_Callback hash_foreach; /**< iterates over all elements in the hash @p h in no specific order */ | ||
2404 | Eet_Descriptor_Hash_Add_Callback hash_add; /**< add a new data @p d with key @p k in hash @p h */ | ||
2405 | Eet_Descriptor_Hash_Free_Callback hash_free; /**< free all entries from the hash @p h */ | ||
2406 | Eet_Descriptor_Str_Direct_Alloc_Callback str_direct_alloc; /**< how to allocate a string directly from file backed/mmaped region pointed by @p str */ | ||
2407 | Eet_Descriptor_Str_Direct_Free_Callback str_direct_free; /**< how to free a string returned by str_direct_alloc */ | ||
2408 | Eet_Descriptor_Type_Get_Callback type_get; /**< get the type, as used in the union or variant mapping, that should be used to store the given data into the eet file. */ | ||
2409 | Eet_Descriptor_Type_Set_Callback type_set; /**< called when loading a mapped type with the given @p type used to describe the type in the descriptor */ | ||
2410 | Eet_Descriptor_Array_Alloc_Callback array_alloc; /**< how to allocate memory for array (usually malloc()) */ | ||
2411 | Eet_Descriptor_Array_Free_Callback array_free; /**< how to free memory for array (usually free()) */ | ||
2412 | } func; | ||
2413 | }; | ||
2414 | |||
2415 | /** | ||
2416 | * @} | ||
2417 | */ | ||
2418 | |||
2419 | /** | ||
2420 | * Create a new empty data structure descriptor. | ||
2421 | * @param name The string name of this data structure (most be a | ||
2422 | * global constant and never change). | ||
2423 | * @param size The size of the struct (in bytes). | ||
2424 | * @param func_list_next The function to get the next list node. | ||
2425 | * @param func_list_append The function to append a member to a list. | ||
2426 | * @param func_list_data The function to get the data from a list node. | ||
2427 | * @param func_list_free The function to free an entire linked list. | ||
2428 | * @param func_hash_foreach The function to iterate through all | ||
2429 | * hash table entries. | ||
2430 | * @param func_hash_add The function to add a member to a hash table. | ||
2431 | * @param func_hash_free The function to free an entire hash table. | ||
2432 | * @return A new empty data descriptor. | ||
2433 | * | ||
2434 | * This function creates a new data descriptore and returns a handle to the | ||
2435 | * new data descriptor. On creation it will be empty, containing no contents | ||
2436 | * describing anything other than the shell of the data structure. | ||
2437 | * | ||
2438 | * You add structure members to the data descriptor using the macros | ||
2439 | * EET_DATA_DESCRIPTOR_ADD_BASIC(), EET_DATA_DESCRIPTOR_ADD_SUB() and | ||
2440 | * EET_DATA_DESCRIPTOR_ADD_LIST(), depending on what type of member you are | ||
2441 | * adding to the description. | ||
2442 | * | ||
2443 | * Once you have described all the members of a struct you want loaded, or | ||
2444 | * saved eet can load and save those members for you, encode them into | ||
2445 | * endian-independent serialised data chunks for transmission across a | ||
2446 | * a network or more. | ||
2447 | * | ||
2448 | * The function pointers to the list and hash table functions are only | ||
2449 | * needed if you use those data types, else you can pass NULL instead. | ||
2450 | * | ||
2451 | * @since 1.0.0 | ||
2452 | * @ingroup Eet_Data_Group | ||
2453 | * | ||
2454 | * @deprecated use eet_data_descriptor_stream_new() or | ||
2455 | * eet_data_descriptor_file_new() | ||
2456 | */ | ||
2457 | EINA_DEPRECATED EAPI Eet_Data_Descriptor * | ||
2458 | eet_data_descriptor_new(const char *name, | ||
2459 | int size, | ||
2460 | Eet_Descriptor_List_Next_Callback func_list_next, | ||
2461 | Eet_Descriptor_List_Append_Callback func_list_append, | ||
2462 | Eet_Descriptor_List_Data_Callback func_list_data, | ||
2463 | Eet_Descriptor_List_Free_Callback func_list_free, | ||
2464 | Eet_Descriptor_Hash_Foreach_Callback func_hash_foreach, | ||
2465 | Eet_Descriptor_Hash_Add_Callback func_hash_add, | ||
2466 | Eet_Descriptor_Hash_Free_Callback func_hash_free); | ||
2467 | /* | ||
2468 | * FIXME: | ||
2469 | * | ||
2470 | * moving to this api from the old above. this will break things when the | ||
2471 | * move happens - but be warned | ||
2472 | */ | ||
2473 | EINA_DEPRECATED EAPI Eet_Data_Descriptor * | ||
2474 | eet_data_descriptor2_new(const Eet_Data_Descriptor_Class *eddc); | ||
2475 | EINA_DEPRECATED EAPI Eet_Data_Descriptor * | ||
2476 | eet_data_descriptor3_new(const Eet_Data_Descriptor_Class *eddc); | ||
2477 | |||
2478 | /** | ||
2479 | * This function creates a new data descriptor and returns a handle to the | ||
2480 | * new data descriptor. On creation it will be empty, containing no contents | ||
2481 | * describing anything other than the shell of the data structure. | ||
2482 | * @param eddc The class from where to create the data descriptor. | ||
2483 | * | ||
2484 | * You add structure members to the data descriptor using the macros | ||
2485 | * EET_DATA_DESCRIPTOR_ADD_BASIC(), EET_DATA_DESCRIPTOR_ADD_SUB() and | ||
2486 | * EET_DATA_DESCRIPTOR_ADD_LIST(), depending on what type of member you are | ||
2487 | * adding to the description. | ||
2488 | * | ||
2489 | * Once you have described all the members of a struct you want loaded or | ||
2490 | * savedi, eet can load and save those members for you, encode them into | ||
2491 | * endian-independent serialised data chunks for transmission across a | ||
2492 | * a network or more. | ||
2493 | * | ||
2494 | * This function specially ignores str_direct_alloc and str_direct_free. It | ||
2495 | * is useful when the eet_data you are reading doesn't have a dictionary, | ||
2496 | * like network stream or IPC. It also mean that all string will be allocated | ||
2497 | * and duplicated in memory. | ||
2498 | * | ||
2499 | * @since 1.2.3 | ||
2500 | * @ingroup Eet_Data_Group | ||
2501 | */ | ||
2502 | EAPI Eet_Data_Descriptor * | ||
2503 | eet_data_descriptor_stream_new(const Eet_Data_Descriptor_Class *eddc); | ||
2504 | |||
2505 | /** | ||
2506 | * This function creates a new data descriptor and returns a handle to the | ||
2507 | * new data descriptor. On creation it will be empty, containing no contents | ||
2508 | * describing anything other than the shell of the data structure. | ||
2509 | * @param eddc The class from where to create the data descriptor. | ||
2510 | * | ||
2511 | * You add structure members to the data descriptor using the macros | ||
2512 | * EET_DATA_DESCRIPTOR_ADD_BASIC(), EET_DATA_DESCRIPTOR_ADD_SUB() and | ||
2513 | * EET_DATA_DESCRIPTOR_ADD_LIST(), depending on what type of member you are | ||
2514 | * adding to the description. | ||
2515 | * | ||
2516 | * Once you have described all the members of a struct you want loaded or | ||
2517 | * savedi, eet can load and save those members for you, encode them into | ||
2518 | * endian-independent serialised data chunks for transmission across a | ||
2519 | * a network or more. | ||
2520 | * | ||
2521 | * This function uses str_direct_alloc and str_direct_free. It is | ||
2522 | * useful when the eet_data you are reading come from a file and | ||
2523 | * have a dictionary. This will reduce memory use and improve the | ||
2524 | * possibility for the OS to page this string out. | ||
2525 | * However, the load speed and memory saving comes with some drawbacks to keep | ||
2526 | * in mind. If you never modify the contents of the structures loaded from | ||
2527 | * the file, all you need to remember is that closing the eet file will make | ||
2528 | * the strings go away. On the other hand, should you need to free a string, | ||
2529 | * before doing so you have to verify that it's not part of the eet dictionary. | ||
2530 | * You can do this in the following way, assuming @p ef is a valid Eet_File | ||
2531 | * and @p str is a string loaded from said file. | ||
2532 | * | ||
2533 | * @code | ||
2534 | * void eet_string_free(Eet_File *ef, const char *str) | ||
2535 | * { | ||
2536 | * Eet_Dictionary *dict = eet_dictionary_get(ef); | ||
2537 | * if (dict && eet_dictionary_string_check(dict, str)) | ||
2538 | * { | ||
2539 | * // The file contains a dictionary and the given string is a part of | ||
2540 | * // of it, so we can't free it, just return. | ||
2541 | * return; | ||
2542 | * } | ||
2543 | * // We assume eina_stringshare was used on the descriptor | ||
2544 | * eina_stringshare_del(str); | ||
2545 | * } | ||
2546 | * @endcode | ||
2547 | * | ||
2548 | * @since 1.2.3 | ||
2549 | * @ingroup Eet_Data_Group | ||
2550 | */ | ||
2551 | EAPI Eet_Data_Descriptor * | ||
2552 | eet_data_descriptor_file_new(const Eet_Data_Descriptor_Class *eddc); | ||
2553 | |||
2554 | /** | ||
2555 | * This function is an helper that set all the parameters of an | ||
2556 | * Eet_Data_Descriptor_Class correctly when you use Eina data type | ||
2557 | * with a stream. | ||
2558 | * @param eddc The Eet_Data_Descriptor_Class you want to set. | ||
2559 | * @param eddc_size The size of the Eet_Data_Descriptor_Class at the compilation time. | ||
2560 | * @param name The name of the structure described by this class. | ||
2561 | * @param size The size of the structure described by this class. | ||
2562 | * @return EINA_TRUE if the structure was correctly set (The only | ||
2563 | * reason that could make it fail is if you did give wrong | ||
2564 | * parameter). | ||
2565 | * | ||
2566 | * @note Unless there's a very specific reason to use this function directly, | ||
2567 | * the EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET macro is recommended. | ||
2568 | * | ||
2569 | * @since 1.2.3 | ||
2570 | * @ingroup Eet_Data_Group | ||
2571 | */ | ||
2572 | EAPI Eina_Bool | ||
2573 | eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, | ||
2574 | unsigned int eddc_size, | ||
2575 | const char *name, | ||
2576 | int size); | ||
2577 | |||
2578 | /** | ||
2579 | * This macro is an helper that set all the parameter of an | ||
2580 | * Eet_Data_Descriptor_Class correctly when you use Eina data type | ||
2581 | * with stream. | ||
2582 | * @param clas The Eet_Data_Descriptor_Class you want to set. | ||
2583 | * @param type The type of the structure described by this class. | ||
2584 | * @return EINA_TRUE if the structure was correctly set (The only | ||
2585 | * reason that could make it fail is if you did give wrong | ||
2586 | * parameter). | ||
2587 | * | ||
2588 | * @see eet_data_descriptor_stream_new | ||
2589 | * @since 1.2.3 | ||
2590 | * @ingroup Eet_Data_Group | ||
2591 | */ | ||
2592 | #define EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(clas, type) \ | ||
2593 | (eet_eina_stream_data_descriptor_class_set(clas, sizeof (*(clas)), # type, sizeof(type))) | ||
2594 | |||
2595 | /** | ||
2596 | * This function is an helper that set all the parameter of an | ||
2597 | * Eet_Data_Descriptor_Class correctly when you use Eina data type | ||
2598 | * with a file. | ||
2599 | * @param eddc The Eet_Data_Descriptor_Class you want to set. | ||
2600 | * @param eddc_size The size of the Eet_Data_Descriptor_Class at the compilation time. | ||
2601 | * @param name The name of the structure described by this class. | ||
2602 | * @param size The size of the structure described by this class. | ||
2603 | * @return EINA_TRUE if the structure was correctly set (The only | ||
2604 | * reason that could make it fail is if you did give wrong | ||
2605 | * parameter). | ||
2606 | * | ||
2607 | * @note Unless there's a very specific reason to use this function directly, | ||
2608 | * the EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET macro is recommended. | ||
2609 | * | ||
2610 | * @since 1.2.3 | ||
2611 | * @ingroup Eet_Data_Group | ||
2612 | */ | ||
2613 | EAPI Eina_Bool | ||
2614 | eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, | ||
2615 | unsigned int eddc_size, | ||
2616 | const char *name, | ||
2617 | int size); | ||
2618 | |||
2619 | /** | ||
2620 | * This macro is an helper that set all the parameter of an | ||
2621 | * Eet_Data_Descriptor_Class correctly when you use Eina data type | ||
2622 | * with file. | ||
2623 | * @param clas The Eet_Data_Descriptor_Class you want to set. | ||
2624 | * @param type The type of the structure described by this class. | ||
2625 | * @return EINA_TRUE if the structure was correctly set (The only | ||
2626 | * reason that could make it fail is if you did give wrong | ||
2627 | * parameter). | ||
2628 | * | ||
2629 | * @see eet_data_descriptor_file_new | ||
2630 | * @since 1.2.3 | ||
2631 | * @ingroup Eet_Data_Group | ||
2632 | */ | ||
2633 | #define EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(clas, type) \ | ||
2634 | (eet_eina_file_data_descriptor_class_set(clas, sizeof (*(clas)), # type, sizeof(type))) | ||
2635 | |||
2636 | /** | ||
2637 | * This function frees a data descriptor when it is not needed anymore. | ||
2638 | * @param edd The data descriptor to free. | ||
2639 | * | ||
2640 | * This function takes a data descriptor handle as a parameter and frees all | ||
2641 | * data allocated for the data descriptor and the handle itself. After this | ||
2642 | * call the descriptor is no longer valid. | ||
2643 | * | ||
2644 | * @since 1.0.0 | ||
2645 | * @ingroup Eet_Data_Group | ||
2646 | */ | ||
2647 | EAPI void | ||
2648 | eet_data_descriptor_free(Eet_Data_Descriptor *edd); | ||
2649 | |||
2650 | /** | ||
2651 | * This function is an internal used by macros. | ||
2652 | * | ||
2653 | * This function is used by macros EET_DATA_DESCRIPTOR_ADD_BASIC(), | ||
2654 | * EET_DATA_DESCRIPTOR_ADD_SUB() and EET_DATA_DESCRIPTOR_ADD_LIST(). It is | ||
2655 | * complex to use by hand and should be left to be used by the macros, and | ||
2656 | * thus is not documented. | ||
2657 | * | ||
2658 | * @param edd The data descriptor handle to add element (member). | ||
2659 | * @param name The name of element to be serialized. | ||
2660 | * @param type The type of element to be serialized, like | ||
2661 | * #EET_T_INT. If #EET_T_UNKNOW, then it is considered to be a | ||
2662 | * group, list or hash. | ||
2663 | * @param group_type If element type is #EET_T_UNKNOW, then the @p | ||
2664 | * group_type will speficy if it is a list (#EET_G_LIST), | ||
2665 | * array (#EET_G_ARRAY) and so on. If #EET_G_UNKNOWN, then | ||
2666 | * the member is a subtype (pointer to another type defined by | ||
2667 | * another #Eet_Data_Descriptor). | ||
2668 | * @param offset byte offset inside the source memory to be serialized. | ||
2669 | * @param count number of elements (if #EET_G_ARRAY or #EET_G_VAR_ARRAY). | ||
2670 | * @param counter_name variable that defines the name of number of elements. | ||
2671 | * @param subtype If contains a subtype, then its data descriptor. | ||
2672 | * | ||
2673 | * @since 1.0.0 | ||
2674 | * @ingroup Eet_Data_Group | ||
2675 | */ | ||
2676 | EAPI void | ||
2677 | eet_data_descriptor_element_add(Eet_Data_Descriptor *edd, | ||
2678 | const char *name, | ||
2679 | int type, | ||
2680 | int group_type, | ||
2681 | int offset, | ||
2682 | /* int count_offset, */ | ||
2683 | int count, | ||
2684 | const char *counter_name, | ||
2685 | Eet_Data_Descriptor *subtype); | ||
2686 | |||
2687 | /** | ||
2688 | * Read a data structure from an eet file and decodes it. | ||
2689 | * @param ef The eet file handle to read from. | ||
2690 | * @param edd The data descriptor handle to use when decoding. | ||
2691 | * @param name The key the data is stored under in the eet file. | ||
2692 | * @return A pointer to the decoded data structure. | ||
2693 | * | ||
2694 | * This function decodes a data structure stored in an eet file, returning | ||
2695 | * a pointer to it if it decoded successfully, or NULL on failure. This | ||
2696 | * can save a programmer dozens of hours of work in writing configuration | ||
2697 | * file parsing and writing code, as eet does all that work for the program | ||
2698 | * and presents a program-friendly data structure, just as the programmer | ||
2699 | * likes. Eet can handle members being added or deleted from the data in | ||
2700 | * storage and safely zero-fills unfilled members if they were not found | ||
2701 | * in the data. It checks sizes and headers whenever it reads data, allowing | ||
2702 | * the programmer to not worry about corrupt data. | ||
2703 | * | ||
2704 | * Once a data structure has been described by the programmer with the | ||
2705 | * fields they wish to save or load, storing or retrieving a data structure | ||
2706 | * from an eet file, or from a chunk of memory is as simple as a single | ||
2707 | * function call. | ||
2708 | * | ||
2709 | * @see eet_data_read_cipher() | ||
2710 | * | ||
2711 | * @since 1.0.0 | ||
2712 | * @ingroup Eet_Data_Group | ||
2713 | */ | ||
2714 | EAPI void * | ||
2715 | eet_data_read(Eet_File *ef, | ||
2716 | Eet_Data_Descriptor *edd, | ||
2717 | const char *name); | ||
2718 | |||
2719 | /** | ||
2720 | * Write a data structure from memory and store in an eet file. | ||
2721 | * @param ef The eet file handle to write to. | ||
2722 | * @param edd The data descriptor to use when encoding. | ||
2723 | * @param name The key to store the data under in the eet file. | ||
2724 | * @param data A pointer to the data structure to ssave and encode. | ||
2725 | * @param compress Compression flags for storage. | ||
2726 | * @return bytes written on successful write, 0 on failure. | ||
2727 | * | ||
2728 | * This function is the reverse of eet_data_read(), saving a data structure | ||
2729 | * to an eet file. The file must have been opening in write mode and the data | ||
2730 | * will be kept in memory until the file is either closed or eet_sync() is | ||
2731 | * called to flush any unwritten changes. | ||
2732 | * | ||
2733 | * @see eet_data_write_cipher() | ||
2734 | * | ||
2735 | * @since 1.0.0 | ||
2736 | * @ingroup Eet_Data_Group | ||
2737 | */ | ||
2738 | EAPI int | ||
2739 | eet_data_write(Eet_File *ef, | ||
2740 | Eet_Data_Descriptor *edd, | ||
2741 | const char *name, | ||
2742 | const void *data, | ||
2743 | int compress); | ||
2744 | |||
2745 | typedef void (*Eet_Dump_Callback)(void *data, const char *str); | ||
2746 | |||
2747 | /** | ||
2748 | * Dump an eet encoded data structure into ascii text | ||
2749 | * @param data_in The pointer to the data to decode into a struct. | ||
2750 | * @param size_in The size of the data pointed to in bytes. | ||
2751 | * @param dumpfunc The function to call passed a string when new | ||
2752 | * data is converted to text | ||
2753 | * @param dumpdata The data to pass to the @p dumpfunc callback. | ||
2754 | * @return 1 on success, 0 on failure | ||
2755 | * | ||
2756 | * This function will take a chunk of data encoded by | ||
2757 | * eet_data_descriptor_encode() and convert it into human readable | ||
2758 | * ascii text. It does this by calling the @p dumpfunc callback | ||
2759 | * for all new text that is generated. This callback should append | ||
2760 | * to any existing text buffer and will be passed the pointer @p | ||
2761 | * dumpdata as a parameter as well as a string with new text to be | ||
2762 | * appended. | ||
2763 | * | ||
2764 | * Example: | ||
2765 | * | ||
2766 | * @code | ||
2767 | * void output(void *data, const char *string) | ||
2768 | * { | ||
2769 | * printf("%s", string); | ||
2770 | * } | ||
2771 | * | ||
2772 | * void dump(const char *file) | ||
2773 | * { | ||
2774 | * FILE *f; | ||
2775 | * int len; | ||
2776 | * void *data; | ||
2777 | * | ||
2778 | * f = fopen(file, "r"); | ||
2779 | * fseek(f, 0, SEEK_END); | ||
2780 | * len = ftell(f); | ||
2781 | * rewind(f); | ||
2782 | * data = malloc(len); | ||
2783 | * fread(data, len, 1, f); | ||
2784 | * fclose(f); | ||
2785 | * eet_data_text_dump(data, len, output, NULL); | ||
2786 | * } | ||
2787 | * @endcode | ||
2788 | * | ||
2789 | * @see eet_data_text_dump_cipher() | ||
2790 | * | ||
2791 | * @since 1.0.0 | ||
2792 | * @ingroup Eet_Data_Group | ||
2793 | */ | ||
2794 | EAPI int | ||
2795 | eet_data_text_dump(const void *data_in, | ||
2796 | int size_in, | ||
2797 | Eet_Dump_Callback dumpfunc, | ||
2798 | void *dumpdata); | ||
2799 | |||
2800 | /** | ||
2801 | * Take an ascii encoding from eet_data_text_dump() and re-encode in binary. | ||
2802 | * @param text The pointer to the string data to parse and encode. | ||
2803 | * @param textlen The size of the string in bytes (not including 0 | ||
2804 | * byte terminator). | ||
2805 | * @param size_ret This gets filled in with the encoded data blob | ||
2806 | * size in bytes. | ||
2807 | * @return The encoded data on success, NULL on failure. | ||
2808 | * | ||
2809 | * This function will parse the string pointed to by @p text and return | ||
2810 | * an encoded data lump the same way eet_data_descriptor_encode() takes an | ||
2811 | * in-memory data struct and encodes into a binary blob. @p text is a normal | ||
2812 | * C string. | ||
2813 | * | ||
2814 | * @see eet_data_text_undump_cipher() | ||
2815 | * | ||
2816 | * @since 1.0.0 | ||
2817 | * @ingroup Eet_Data_Group | ||
2818 | */ | ||
2819 | EAPI void * | ||
2820 | eet_data_text_undump(const char *text, | ||
2821 | int textlen, | ||
2822 | int *size_ret); | ||
2823 | |||
2824 | /** | ||
2825 | * Dump an eet encoded data structure from an eet file into ascii text | ||
2826 | * @param ef A valid eet file handle. | ||
2827 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
2828 | * @param dumpfunc The function to call passed a string when new | ||
2829 | * data is converted to text | ||
2830 | * @param dumpdata The data to pass to the @p dumpfunc callback. | ||
2831 | * @return 1 on success, 0 on failure | ||
2832 | * | ||
2833 | * This function will take an open and valid eet file from | ||
2834 | * eet_open() request the data encoded by | ||
2835 | * eet_data_descriptor_encode() corresponding to the key @p name | ||
2836 | * and convert it into human readable ascii text. It does this by | ||
2837 | * calling the @p dumpfunc callback for all new text that is | ||
2838 | * generated. This callback should append to any existing text | ||
2839 | * buffer and will be passed the pointer @p dumpdata as a parameter | ||
2840 | * as well as a string with new text to be appended. | ||
2841 | * | ||
2842 | * @see eet_data_dump_cipher() | ||
2843 | * | ||
2844 | * @since 1.0.0 | ||
2845 | * @ingroup Eet_Data_Group | ||
2846 | */ | ||
2847 | EAPI int | ||
2848 | eet_data_dump(Eet_File *ef, | ||
2849 | const char *name, | ||
2850 | Eet_Dump_Callback dumpfunc, | ||
2851 | void *dumpdata); | ||
2852 | |||
2853 | /** | ||
2854 | * Take an ascii encoding from eet_data_dump() and re-encode in binary. | ||
2855 | * @param ef A valid eet file handle. | ||
2856 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
2857 | * @param text The pointer to the string data to parse and encode. | ||
2858 | * @param textlen The size of the string in bytes (not including 0 | ||
2859 | * byte terminator). | ||
2860 | * @param compress Compression flags (1 == compress, 0 = don't compress). | ||
2861 | * @return 1 on success, 0 on failure | ||
2862 | * | ||
2863 | * This function will parse the string pointed to by @p text, | ||
2864 | * encode it the same way eet_data_descriptor_encode() takes an | ||
2865 | * in-memory data struct and encodes into a binary blob. | ||
2866 | * | ||
2867 | * The data (optionally compressed) will be in ram, pending a flush to | ||
2868 | * disk (it will stay in ram till the eet file handle is closed though). | ||
2869 | * | ||
2870 | * @see eet_data_undump_cipher() | ||
2871 | * | ||
2872 | * @since 1.0.0 | ||
2873 | * @ingroup Eet_Data_Group | ||
2874 | */ | ||
2875 | EAPI int | ||
2876 | eet_data_undump(Eet_File *ef, | ||
2877 | const char *name, | ||
2878 | const char *text, | ||
2879 | int textlen, | ||
2880 | int compress); | ||
2881 | |||
2882 | /** | ||
2883 | * Decode a data structure from an arbitrary location in memory. | ||
2884 | * @param edd The data descriptor to use when decoding. | ||
2885 | * @param data_in The pointer to the data to decode into a struct. | ||
2886 | * @param size_in The size of the data pointed to in bytes. | ||
2887 | * @return NULL on failure, or a valid decoded struct pointer on success. | ||
2888 | * | ||
2889 | * This function will decode a data structure that has been encoded using | ||
2890 | * eet_data_descriptor_encode(), and return a data structure with all its | ||
2891 | * elements filled out, if successful, or NULL on failure. | ||
2892 | * | ||
2893 | * The data to be decoded is stored at the memory pointed to by @p data_in, | ||
2894 | * and is described by the descriptor pointed to by @p edd. The data size is | ||
2895 | * passed in as the value to @p size_in, ande must be greater than 0 to | ||
2896 | * succeed. | ||
2897 | * | ||
2898 | * This function is useful for decoding data structures delivered to the | ||
2899 | * application by means other than an eet file, such as an IPC or socket | ||
2900 | * connection, raw files, shared memory etc. | ||
2901 | * | ||
2902 | * Please see eet_data_read() for more information. | ||
2903 | * | ||
2904 | * @see eet_data_descriptor_decode_cipher() | ||
2905 | * | ||
2906 | * @since 1.0.0 | ||
2907 | * @ingroup Eet_Data_Group | ||
2908 | */ | ||
2909 | EAPI void * | ||
2910 | eet_data_descriptor_decode(Eet_Data_Descriptor *edd, | ||
2911 | const void *data_in, | ||
2912 | int size_in); | ||
2913 | |||
2914 | /** | ||
2915 | * Encode a dsata struct to memory and return that encoded data. | ||
2916 | * @param edd The data descriptor to use when encoding. | ||
2917 | * @param data_in The pointer to the struct to encode into data. | ||
2918 | * @param size_ret pointer to the an int to be filled with the decoded size. | ||
2919 | * @return NULL on failure, or a valid encoded data chunk on success. | ||
2920 | * | ||
2921 | * This function takes a data structutre in memory and encodes it into a | ||
2922 | * serialised chunk of data that can be decoded again by | ||
2923 | * eet_data_descriptor_decode(). This is useful for being able to transmit | ||
2924 | * data structures across sockets, pipes, IPC or shared file mechanisms, | ||
2925 | * without having to worry about memory space, machine type, endianess etc. | ||
2926 | * | ||
2927 | * The parameter @p edd must point to a valid data descriptor, and | ||
2928 | * @p data_in must point to the right data structure to encode. If not, the | ||
2929 | * encoding may fail. | ||
2930 | * | ||
2931 | * On success a non NULL valid pointer is returned and what @p size_ret | ||
2932 | * points to is set to the size of this decoded data, in bytes. When the | ||
2933 | * encoded data is no longer needed, call free() on it. On failure NULL is | ||
2934 | * returned and what @p size_ret points to is set to 0. | ||
2935 | * | ||
2936 | * Please see eet_data_write() for more information. | ||
2937 | * | ||
2938 | * @see eet_data_descriptor_encode_cipher() | ||
2939 | * | ||
2940 | * @since 1.0.0 | ||
2941 | * @ingroup Eet_Data_Group | ||
2942 | */ | ||
2943 | EAPI void * | ||
2944 | eet_data_descriptor_encode(Eet_Data_Descriptor *edd, | ||
2945 | const void *data_in, | ||
2946 | int *size_ret); | ||
2947 | |||
2948 | /** | ||
2949 | * Add a basic data element to a data descriptor. | ||
2950 | * @param edd The data descriptor to add the type to. | ||
2951 | * @param struct_type The type of the struct. | ||
2952 | * @param name The string name to use to encode/decode this member | ||
2953 | * (must be a constant global and never change). | ||
2954 | * @param member The struct member itself to be encoded. | ||
2955 | * @param type The type of the member to encode. | ||
2956 | * | ||
2957 | * This macro is a convenience macro provided to add a member to | ||
2958 | * the data descriptor @p edd. The type of the structure is | ||
2959 | * provided as the @p struct_type parameter (for example: struct | ||
2960 | * my_struct). The @p name parameter defines a string that will be | ||
2961 | * used to uniquely name that member of the struct (it is suggested | ||
2962 | * to use the struct member itself). The @p member parameter is | ||
2963 | * the actual struct member itself (for example: values), and @p type is the | ||
2964 | * basic data type of the member which must be one of: EET_T_CHAR, EET_T_SHORT, | ||
2965 | * EET_T_INT, EET_T_LONG_LONG, EET_T_FLOAT, EET_T_DOUBLE, EET_T_UCHAR, | ||
2966 | * EET_T_USHORT, EET_T_UINT, EET_T_ULONG_LONG or EET_T_STRING. | ||
2967 | * | ||
2968 | * @since 1.0.0 | ||
2969 | * @ingroup Eet_Data_Group | ||
2970 | */ | ||
2971 | #define EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct_type, name, member, type) \ | ||
2972 | do { \ | ||
2973 | struct_type ___ett; \ | ||
2974 | eet_data_descriptor_element_add(edd, name, type, EET_G_UNKNOWN, \ | ||
2975 | (char *)(& (___ett.member)) - \ | ||
2976 | (char *)(& (___ett)), \ | ||
2977 | 0, /* 0, */ NULL, NULL); \ | ||
2978 | } while(0) | ||
2979 | |||
2980 | /** | ||
2981 | * Add a sub-element type to a data descriptor | ||
2982 | * @param edd The data descriptor to add the type to. | ||
2983 | * @param struct_type The type of the struct. | ||
2984 | * @param name The string name to use to encode/decode this member | ||
2985 | * (must be a constant global and never change). | ||
2986 | * @param member The struct member itself to be encoded. | ||
2987 | * @param subtype The type of sub-type struct to add. | ||
2988 | * | ||
2989 | * This macro lets you easily add a sub-type (a struct that's pointed to | ||
2990 | * by this one). All the parameters are the same as for | ||
2991 | * EET_DATA_DESCRIPTOR_ADD_BASIC(), with the @p subtype being the exception. | ||
2992 | * This must be the data descriptor of the struct that is pointed to by | ||
2993 | * this element. | ||
2994 | * | ||
2995 | * @since 1.0.0 | ||
2996 | * @ingroup Eet_Data_Group | ||
2997 | */ | ||
2998 | #define EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct_type, name, member, subtype) \ | ||
2999 | do { \ | ||
3000 | struct_type ___ett; \ | ||
3001 | eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_UNKNOWN, \ | ||
3002 | (char *)(& (___ett.member)) - \ | ||
3003 | (char *)(& (___ett)), \ | ||
3004 | 0, /* 0, */ NULL, subtype); \ | ||
3005 | } while (0) | ||
3006 | |||
3007 | /** | ||
3008 | * Add a linked list type to a data descriptor | ||
3009 | * @param edd The data descriptor to add the type to. | ||
3010 | * @param struct_type The type of the struct. | ||
3011 | * @param name The string name to use to encode/decode this member | ||
3012 | * (must be a constant global and never change). | ||
3013 | * @param member The struct member itself to be encoded. | ||
3014 | * @param subtype The type of linked list member to add. | ||
3015 | * | ||
3016 | * This macro lets you easily add a linked list of other data types. All the | ||
3017 | * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(), with the | ||
3018 | * @p subtype being the exception. This must be the data descriptor of the | ||
3019 | * element that is in each member of the linked list to be stored. | ||
3020 | * | ||
3021 | * @since 1.0.0 | ||
3022 | * @ingroup Eet_Data_Group | ||
3023 | */ | ||
3024 | #define EET_DATA_DESCRIPTOR_ADD_LIST(edd, struct_type, name, member, subtype) \ | ||
3025 | do { \ | ||
3026 | struct_type ___ett; \ | ||
3027 | eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_LIST, \ | ||
3028 | (char *)(& (___ett.member)) - \ | ||
3029 | (char *)(& (___ett)), \ | ||
3030 | 0, /* 0, */ NULL, subtype); \ | ||
3031 | } while (0) | ||
3032 | |||
3033 | /** | ||
3034 | * Add a linked list of string to a data descriptor | ||
3035 | * @param edd The data descriptor to add the type to. | ||
3036 | * @param struct_type The type of the struct. | ||
3037 | * @param name The string name to use to encode/decode this member | ||
3038 | * (must be a constant global and never change). | ||
3039 | * @param member The struct member itself to be encoded. | ||
3040 | * | ||
3041 | * This macro lets you easily add a linked list of char *. All the | ||
3042 | * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(). | ||
3043 | * | ||
3044 | * @since 1.5.0 | ||
3045 | * @ingroup Eet_Data_Group | ||
3046 | */ | ||
3047 | #define EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct_type, name, member) \ | ||
3048 | do { \ | ||
3049 | struct_type ___ett; \ | ||
3050 | eet_data_descriptor_element_add(edd, name, EET_T_STRING, EET_G_LIST, \ | ||
3051 | (char *)(& (___ett.member)) - \ | ||
3052 | (char *)(& (___ett)), \ | ||
3053 | 0, /* 0, */ NULL, NULL); \ | ||
3054 | } while (0) | ||
3055 | |||
3056 | /** | ||
3057 | * Add a hash type to a data descriptor | ||
3058 | * @param edd The data descriptor to add the type to. | ||
3059 | * @param struct_type The type of the struct. | ||
3060 | * @param name The string name to use to encode/decode this member | ||
3061 | * (must be a constant global and never change). | ||
3062 | * @param member The struct member itself to be encoded. | ||
3063 | * @param subtype The type of hash member to add. | ||
3064 | * | ||
3065 | * This macro lets you easily add a hash of other data types. All the | ||
3066 | * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(), with the | ||
3067 | * @p subtype being the exception. This must be the data descriptor of the | ||
3068 | * element that is in each member of the hash to be stored. | ||
3069 | * The hash keys must be strings. | ||
3070 | * | ||
3071 | * @since 1.0.0 | ||
3072 | * @ingroup Eet_Data_Group | ||
3073 | */ | ||
3074 | #define EET_DATA_DESCRIPTOR_ADD_HASH(edd, struct_type, name, member, subtype) \ | ||
3075 | do { \ | ||
3076 | struct_type ___ett; \ | ||
3077 | eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_HASH, \ | ||
3078 | (char *)(& (___ett.member)) - \ | ||
3079 | (char *)(& (___ett)), \ | ||
3080 | 0, /* 0, */ NULL, subtype); \ | ||
3081 | } while (0) | ||
3082 | |||
3083 | /** | ||
3084 | * Add a hash of string to a data descriptor | ||
3085 | * @param edd The data descriptor to add the type to. | ||
3086 | * @param struct_type The type of the struct. | ||
3087 | * @param name The string name to use to encode/decode this member | ||
3088 | * (must be a constant global and never change). | ||
3089 | * @param member The struct member itself to be encoded. | ||
3090 | * | ||
3091 | * This macro lets you easily add a hash of string elements. All the | ||
3092 | * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_HASH(). | ||
3093 | * | ||
3094 | * @since 1.3.4 | ||
3095 | * @ingroup Eet_Data_Group | ||
3096 | */ | ||
3097 | #define EET_DATA_DESCRIPTOR_ADD_HASH_STRING(edd, struct_type, name, member) \ | ||
3098 | do { \ | ||
3099 | struct_type ___ett; \ | ||
3100 | eet_data_descriptor_element_add(edd, name, EET_T_STRING, EET_G_HASH, \ | ||
3101 | (char *)(& (___ett.member)) - \ | ||
3102 | (char *)(& (___ett)), \ | ||
3103 | 0, /* 0, */ NULL, NULL); \ | ||
3104 | } while (0) | ||
3105 | |||
3106 | /** | ||
3107 | * Add an array of basic data elements to a data descriptor. | ||
3108 | * @param edd The data descriptor to add the type to. | ||
3109 | * @param struct_type The type of the struct. | ||
3110 | * @param name The string name to use to encode/decode this member | ||
3111 | * (must be a constant global and never change). | ||
3112 | * @param member The struct member itself to be encoded. | ||
3113 | * @param type The type of the member to encode. | ||
3114 | * | ||
3115 | * This macro lets you easily add a fixed size array of basic data | ||
3116 | * types. All the parameters are the same as for | ||
3117 | * EET_DATA_DESCRIPTOR_ADD_BASIC(). | ||
3118 | * The array must be defined with a fixed size in the declaration of the | ||
3119 | * struct containing it. | ||
3120 | * | ||
3121 | * @since 1.5.0 | ||
3122 | * @ingroup Eet_Data_Group | ||
3123 | */ | ||
3124 | #define EET_DATA_DESCRIPTOR_ADD_BASIC_ARRAY(edd, struct_type, name, member, type) \ | ||
3125 | do { \ | ||
3126 | struct_type ___ett; \ | ||
3127 | eet_data_descriptor_element_add(edd, name, type, EET_G_ARRAY, \ | ||
3128 | (char *)(& (___ett.member)) - \ | ||
3129 | (char *)(& (___ett)), \ | ||
3130 | sizeof(___ett.member) / \ | ||
3131 | sizeof(___ett.member[0]), \ | ||
3132 | NULL, NULL); \ | ||
3133 | } while(0) | ||
3134 | |||
3135 | /** | ||
3136 | * Add a fixed size array type to a data descriptor | ||
3137 | * @param edd The data descriptor to add the type to. | ||
3138 | * @param struct_type The type of the struct. | ||
3139 | * @param name The string name to use to encode/decode this member | ||
3140 | * (must be a constant global and never change). | ||
3141 | * @param member The struct member itself to be encoded. | ||
3142 | * @param subtype The type of hash member to add. | ||
3143 | * | ||
3144 | * This macro lets you easily add a fixed size array of other data | ||
3145 | * types. All the parameters are the same as for | ||
3146 | * EET_DATA_DESCRIPTOR_ADD_BASIC(), with the @p subtype being the | ||
3147 | * exception. This must be the data descriptor of the element that | ||
3148 | * is in each member of the array to be stored. | ||
3149 | * The array must be defined with a fixed size in the declaration of the | ||
3150 | * struct containing it. | ||
3151 | * | ||
3152 | * @since 1.0.2 | ||
3153 | * @ingroup Eet_Data_Group | ||
3154 | */ | ||
3155 | #define EET_DATA_DESCRIPTOR_ADD_ARRAY(edd, struct_type, name, member, subtype) \ | ||
3156 | do { \ | ||
3157 | struct_type ___ett; \ | ||
3158 | eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_ARRAY, \ | ||
3159 | (char *)(& (___ett.member)) - \ | ||
3160 | (char *)(& (___ett)), \ | ||
3161 | /* 0, */ sizeof(___ett.member) / \ | ||
3162 | sizeof(___ett.member[0]), NULL, subtype); \ | ||
3163 | } while (0) | ||
3164 | |||
3165 | /** | ||
3166 | * Add a variable size array type to a data descriptor | ||
3167 | * @param edd The data descriptor to add the type to. | ||
3168 | * @param struct_type The type of the struct. | ||
3169 | * @param name The string name to use to encode/decode this member | ||
3170 | * (must be a constant global and never change). | ||
3171 | * @param member The struct member itself to be encoded. | ||
3172 | * @param subtype The type of hash member to add. | ||
3173 | * | ||
3174 | * This macro lets you easily add a variable size array of other data | ||
3175 | * types. All the parameters are the same as for | ||
3176 | * EET_DATA_DESCRIPTOR_ADD_BASIC(), with the @p subtype being the | ||
3177 | * exception. This must be the data descriptor of the element that | ||
3178 | * is in each member of the array to be stored. This assumes you have | ||
3179 | * a struct member (of type EET_T_INT) called member_count (note the | ||
3180 | * _count appended to the member) that holds the number of items in | ||
3181 | * the array. This array will be allocated separately to the struct it | ||
3182 | * is in. | ||
3183 | * | ||
3184 | * @since 1.0.2 | ||
3185 | * @ingroup Eet_Data_Group | ||
3186 | */ | ||
3187 | #define EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(edd, struct_type, name, member, subtype) \ | ||
3188 | do { \ | ||
3189 | struct_type ___ett; \ | ||
3190 | eet_data_descriptor_element_add(edd, \ | ||
3191 | name, \ | ||
3192 | EET_T_UNKNOW, \ | ||
3193 | EET_G_VAR_ARRAY, \ | ||
3194 | (char *)(& (___ett.member)) - \ | ||
3195 | (char *)(& (___ett)), \ | ||
3196 | (char *)(& (___ett.member ## _count)) - \ | ||
3197 | (char *)(& (___ett)), \ | ||
3198 | /* 0, */ NULL, \ | ||
3199 | subtype); \ | ||
3200 | } while (0) | ||
3201 | |||
3202 | /** | ||
3203 | * Add a variable size array type to a data descriptor | ||
3204 | * @param edd The data descriptor to add the type to. | ||
3205 | * @param struct_type The type of the struct. | ||
3206 | * @param name The string name to use to encode/decode this member | ||
3207 | * (must be a constant global and never change). | ||
3208 | * @param member The struct member itself to be encoded. | ||
3209 | * | ||
3210 | * This macro lets you easily add a variable size array of strings. All | ||
3211 | * the parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(). | ||
3212 | * | ||
3213 | * @since 1.4.0 | ||
3214 | * @ingroup Eet_Data_Group | ||
3215 | */ | ||
3216 | #define EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY_STRING(edd, struct_type, name, member) \ | ||
3217 | do { \ | ||
3218 | struct_type ___ett; \ | ||
3219 | eet_data_descriptor_element_add(edd, \ | ||
3220 | name, \ | ||
3221 | EET_T_STRING, \ | ||
3222 | EET_G_VAR_ARRAY, \ | ||
3223 | (char *)(& (___ett.member)) - \ | ||
3224 | (char *)(& (___ett)), \ | ||
3225 | (char *)(& (___ett.member ## _count)) - \ | ||
3226 | (char *)(& (___ett)), \ | ||
3227 | /* 0, */ NULL, \ | ||
3228 | NULL); \ | ||
3229 | } while (0) | ||
3230 | |||
3231 | /** | ||
3232 | * Add an union type to a data descriptor | ||
3233 | * @param edd The data descriptor to add the type to. | ||
3234 | * @param struct_type The type of the struct. | ||
3235 | * @param name The string name to use to encode/decode this member | ||
3236 | * (must be a constant global and never change). | ||
3237 | * @param member The struct member itself to be encoded. | ||
3238 | * @param type_member The member that give hints on what is in the union. | ||
3239 | * @param unified_type Describe all possible type the union could handle. | ||
3240 | * | ||
3241 | * This macro lets you easily add an union with a member that specify what is inside. | ||
3242 | * The @p unified_type is an Eet_Data_Descriptor, but only the entry that match the name | ||
3243 | * returned by type_get will be used for each serialized data. The type_get and type_set | ||
3244 | * callback of unified_type should be defined. | ||
3245 | * | ||
3246 | * @since 1.2.4 | ||
3247 | * @ingroup Eet_Data_Group | ||
3248 | * @see Eet_Data_Descriptor_Class | ||
3249 | */ | ||
3250 | #define EET_DATA_DESCRIPTOR_ADD_UNION(edd, struct_type, name, member, type_member, unified_type) \ | ||
3251 | do { \ | ||
3252 | struct_type ___ett; \ | ||
3253 | eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_UNION, \ | ||
3254 | (char *)(& (___ett.member)) - \ | ||
3255 | (char *)(& (___ett)), \ | ||
3256 | (char *)(& (___ett.type_member)) - \ | ||
3257 | (char *)(& (___ett)), \ | ||
3258 | NULL, unified_type); \ | ||
3259 | } while (0) | ||
3260 | |||
3261 | /** | ||
3262 | * Add a automatically selectable type to a data descriptor | ||
3263 | * @param edd The data descriptor to add the type to. | ||
3264 | * @param struct_type The type of the struct. | ||
3265 | * @param name The string name to use to encode/decode this member | ||
3266 | * (must be a constant global and never change). | ||
3267 | * @param member The struct member itself to be encoded. | ||
3268 | * @param type_member The member that give hints on what is in the union. | ||
3269 | * @param unified_type Describe all possible type the union could handle. | ||
3270 | * | ||
3271 | * This macro lets you easily define what the content of @p member points to depending of | ||
3272 | * the content of @p type_member. The type_get and type_set callback of unified_type should | ||
3273 | * be defined. If the the type is not know at the time of restoring it, eet will still call | ||
3274 | * type_set of @p unified_type but the pointer will be set to a serialized binary representation | ||
3275 | * of what eet know. This make it possible, to save this pointer again by just returning the string | ||
3276 | * given previously and telling it by setting unknow to EINA_TRUE. | ||
3277 | * | ||
3278 | * @since 1.2.4 | ||
3279 | * @ingroup Eet_Data_Group | ||
3280 | * @see Eet_Data_Descriptor_Class | ||
3281 | */ | ||
3282 | #define EET_DATA_DESCRIPTOR_ADD_VARIANT(edd, struct_type, name, member, type_member, unified_type) \ | ||
3283 | do { \ | ||
3284 | struct_type ___ett; \ | ||
3285 | eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_VARIANT, \ | ||
3286 | (char *)(& (___ett.member)) - \ | ||
3287 | (char *)(& (___ett)), \ | ||
3288 | (char *)(& (___ett.type_member)) - \ | ||
3289 | (char *)(& (___ett)), \ | ||
3290 | NULL, unified_type); \ | ||
3291 | } while (0) | ||
3292 | |||
3293 | /** | ||
3294 | * Add a mapping to a data descriptor that will be used by union, variant or inherited type | ||
3295 | * @param unified_type The data descriptor to add the mapping to. | ||
3296 | * @param name The string name to get/set type. | ||
3297 | * @param subtype The matching data descriptor. | ||
3298 | * | ||
3299 | * @since 1.2.4 | ||
3300 | * @ingroup Eet_Data_Group | ||
3301 | * @see Eet_Data_Descriptor_Class | ||
3302 | */ | ||
3303 | #define EET_DATA_DESCRIPTOR_ADD_MAPPING(unified_type, name, subtype) \ | ||
3304 | eet_data_descriptor_element_add(unified_type, \ | ||
3305 | name, \ | ||
3306 | EET_T_UNKNOW, \ | ||
3307 | EET_G_UNKNOWN, \ | ||
3308 | 0, \ | ||
3309 | 0, \ | ||
3310 | NULL, \ | ||
3311 | subtype) | ||
3312 | |||
3313 | /** | ||
3314 | * @defgroup Eet_Data_Cipher_Group Eet Data Serialization using A Ciphers | ||
3315 | * | ||
3316 | * Most of the @ref Eet_Data_Group have alternative versions that | ||
3317 | * accounts for ciphers to protect their content. | ||
3318 | * | ||
3319 | * @see @ref Eet_Cipher_Group | ||
3320 | * | ||
3321 | * @ingroup Eet_Data_Group | ||
3322 | */ | ||
3323 | |||
3324 | /** | ||
3325 | * Read a data structure from an eet file and decodes it using a cipher. | ||
3326 | * @param ef The eet file handle to read from. | ||
3327 | * @param edd The data descriptor handle to use when decoding. | ||
3328 | * @param name The key the data is stored under in the eet file. | ||
3329 | * @param cipher_key The key to use as cipher. | ||
3330 | * @return A pointer to the decoded data structure. | ||
3331 | * | ||
3332 | * This function decodes a data structure stored in an eet file, returning | ||
3333 | * a pointer to it if it decoded successfully, or NULL on failure. This | ||
3334 | * can save a programmer dozens of hours of work in writing configuration | ||
3335 | * file parsing and writing code, as eet does all that work for the program | ||
3336 | * and presents a program-friendly data structure, just as the programmer | ||
3337 | * likes. Eet can handle members being added or deleted from the data in | ||
3338 | * storage and safely zero-fills unfilled members if they were not found | ||
3339 | * in the data. It checks sizes and headers whenever it reads data, allowing | ||
3340 | * the programmer to not worry about corrupt data. | ||
3341 | * | ||
3342 | * Once a data structure has been described by the programmer with the | ||
3343 | * fields they wish to save or load, storing or retrieving a data structure | ||
3344 | * from an eet file, or from a chunk of memory is as simple as a single | ||
3345 | * function call. | ||
3346 | * | ||
3347 | * @see eet_data_read() | ||
3348 | * | ||
3349 | * @since 1.0.0 | ||
3350 | * @ingroup Eet_Data_Cipher_Group | ||
3351 | */ | ||
3352 | EAPI void * | ||
3353 | eet_data_read_cipher(Eet_File *ef, | ||
3354 | Eet_Data_Descriptor *edd, | ||
3355 | const char *name, | ||
3356 | const char *cipher_key); | ||
3357 | |||
3358 | /** | ||
3359 | * Read a data structure from an eet extended attribute and decodes it using a cipher. | ||
3360 | * @param filename The file to extract the extended attribute from. | ||
3361 | * @param attribute The attribute to get the data from. | ||
3362 | * @param edd The data descriptor handle to use when decoding. | ||
3363 | * @param cipher_key The key to use as cipher. | ||
3364 | * @return A pointer to the decoded data structure. | ||
3365 | * | ||
3366 | * This function decodes a data structure stored in an eet extended attribute, | ||
3367 | * returning a pointer to it if it decoded successfully, or NULL on failure. | ||
3368 | * Eet can handle members being added or deleted from the data in | ||
3369 | * storage and safely zero-fills unfilled members if they were not found | ||
3370 | * in the data. It checks sizes and headers whenever it reads data, allowing | ||
3371 | * the programmer to not worry about corrupt data. | ||
3372 | * | ||
3373 | * Once a data structure has been described by the programmer with the | ||
3374 | * fields they wish to save or load, storing or retrieving a data structure | ||
3375 | * from an eet file, from a chunk of memory or from an extended attribute | ||
3376 | * is as simple as a single function call. | ||
3377 | * | ||
3378 | * @since 1.5.0 | ||
3379 | * @ingroup Eet_Data_Cipher_Group | ||
3380 | */ | ||
3381 | EAPI void * | ||
3382 | eet_data_xattr_cipher_get(const char *filename, | ||
3383 | const char *attribute, | ||
3384 | Eet_Data_Descriptor *edd, | ||
3385 | const char *cipher_key); | ||
3386 | |||
3387 | /** | ||
3388 | * Write a data structure from memory and store in an eet file | ||
3389 | * using a cipher. | ||
3390 | * @param ef The eet file handle to write to. | ||
3391 | * @param edd The data descriptor to use when encoding. | ||
3392 | * @param name The key to store the data under in the eet file. | ||
3393 | * @param cipher_key The key to use as cipher. | ||
3394 | * @param data A pointer to the data structure to ssave and encode. | ||
3395 | * @param compress Compression flags for storage. | ||
3396 | * @return bytes written on successful write, 0 on failure. | ||
3397 | * | ||
3398 | * This function is the reverse of eet_data_read_cipher(), saving a data structure | ||
3399 | * to an eet file. | ||
3400 | * | ||
3401 | * @since 1.0.0 | ||
3402 | * @ingroup Eet_Data_Cipher_Group | ||
3403 | */ | ||
3404 | EAPI int | ||
3405 | eet_data_write_cipher(Eet_File *ef, | ||
3406 | Eet_Data_Descriptor *edd, | ||
3407 | const char *name, | ||
3408 | const char *cipher_key, | ||
3409 | const void *data, | ||
3410 | int compress); | ||
3411 | |||
3412 | /** | ||
3413 | * Write a data structure from memory and store in an eet extended attribute | ||
3414 | * using a cipher. | ||
3415 | * @param filename The file to write the extended attribute to. | ||
3416 | * @param attribute The attribute to store the data to. | ||
3417 | * @param edd The data descriptor to use when encoding. | ||
3418 | * @param cipher_key The key to use as cipher. | ||
3419 | * @param data A pointer to the data structure to ssave and encode. | ||
3420 | * @param flags The policy to use when setting the data. | ||
3421 | * @return EINA_TRUE on success, EINA_FALSE on failure. | ||
3422 | * | ||
3423 | * This function is the reverse of eet_data_xattr_cipher_get(), saving a data structure | ||
3424 | * to an eet extended attribute. | ||
3425 | * | ||
3426 | * @since 1.5.0 | ||
3427 | * @ingroup Eet_Data_Cipher_Group | ||
3428 | */ | ||
3429 | EAPI Eina_Bool | ||
3430 | eet_data_xattr_cipher_set(const char *filename, | ||
3431 | const char *attribute, | ||
3432 | Eet_Data_Descriptor *edd, | ||
3433 | const char *cipher_key, | ||
3434 | const void *data, | ||
3435 | Eina_Xattr_Flags flags); | ||
3436 | |||
3437 | /** | ||
3438 | * Dump an eet encoded data structure into ascii text using a cipher. | ||
3439 | * @param data_in The pointer to the data to decode into a struct. | ||
3440 | * @param cipher_key The key to use as cipher. | ||
3441 | * @param size_in The size of the data pointed to in bytes. | ||
3442 | * @param dumpfunc The function to call passed a string when new | ||
3443 | * data is converted to text | ||
3444 | * @param dumpdata The data to pass to the @p dumpfunc callback. | ||
3445 | * @return 1 on success, 0 on failure | ||
3446 | * | ||
3447 | * This function will take a chunk of data encoded by | ||
3448 | * eet_data_descriptor_encode() and convert it into human readable | ||
3449 | * ascii text. It does this by calling the @p dumpfunc callback | ||
3450 | * for all new text that is generated. This callback should append | ||
3451 | * to any existing text buffer and will be passed the pointer @p | ||
3452 | * dumpdata as a parameter as well as a string with new text to be | ||
3453 | * appended. | ||
3454 | * | ||
3455 | * Example: | ||
3456 | * | ||
3457 | * @code | ||
3458 | * void output(void *data, const char *string) | ||
3459 | * { | ||
3460 | * printf("%s", string); | ||
3461 | * } | ||
3462 | * | ||
3463 | * void dump(const char *file) | ||
3464 | * { | ||
3465 | * FILE *f; | ||
3466 | * int len; | ||
3467 | * void *data; | ||
3468 | * | ||
3469 | * f = fopen(file, "r"); | ||
3470 | * fseek(f, 0, SEEK_END); | ||
3471 | * len = ftell(f); | ||
3472 | * rewind(f); | ||
3473 | * data = malloc(len); | ||
3474 | * fread(data, len, 1, f); | ||
3475 | * fclose(f); | ||
3476 | * eet_data_text_dump_cipher(data, cipher_key, len, output, NULL); | ||
3477 | * } | ||
3478 | * @endcode | ||
3479 | * | ||
3480 | * @see eet_data_text_dump() | ||
3481 | * | ||
3482 | * @since 1.0.0 | ||
3483 | * @ingroup Eet_Data_Cipher_Group | ||
3484 | */ | ||
3485 | EAPI int | ||
3486 | eet_data_text_dump_cipher(const void *data_in, | ||
3487 | const char *cipher_key, | ||
3488 | int size_in, | ||
3489 | Eet_Dump_Callback dumpfunc, | ||
3490 | void *dumpdata); | ||
3491 | |||
3492 | /** | ||
3493 | * Take an ascii encoding from eet_data_text_dump() and re-encode | ||
3494 | * in binary using a cipher. | ||
3495 | * @param text The pointer to the string data to parse and encode. | ||
3496 | * @param cipher_key The key to use as cipher. | ||
3497 | * @param textlen The size of the string in bytes (not including 0 | ||
3498 | * byte terminator). | ||
3499 | * @param size_ret This gets filled in with the encoded data blob | ||
3500 | * size in bytes. | ||
3501 | * @return The encoded data on success, NULL on failure. | ||
3502 | * | ||
3503 | * This function will parse the string pointed to by @p text and return | ||
3504 | * an encoded data lump the same way eet_data_descriptor_encode() takes an | ||
3505 | * in-memory data struct and encodes into a binary blob. @p text is a normal | ||
3506 | * C string. | ||
3507 | * | ||
3508 | * @see eet_data_text_undump() | ||
3509 | * | ||
3510 | * @since 1.0.0 | ||
3511 | * @ingroup Eet_Data_Cipher_Group | ||
3512 | */ | ||
3513 | EAPI void * | ||
3514 | eet_data_text_undump_cipher(const char *text, | ||
3515 | const char *cipher_key, | ||
3516 | int textlen, | ||
3517 | int *size_ret); | ||
3518 | |||
3519 | /** | ||
3520 | * Dump an eet encoded data structure from an eet file into ascii | ||
3521 | * text using a cipher. | ||
3522 | * @param ef A valid eet file handle. | ||
3523 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
3524 | * @param cipher_key The key to use as cipher. | ||
3525 | * @param dumpfunc The function to call passed a string when new | ||
3526 | * data is converted to text | ||
3527 | * @param dumpdata The data to pass to the @p dumpfunc callback. | ||
3528 | * @return 1 on success, 0 on failure | ||
3529 | * | ||
3530 | * This function will take an open and valid eet file from | ||
3531 | * eet_open() request the data encoded by | ||
3532 | * eet_data_descriptor_encode() corresponding to the key @p name | ||
3533 | * and convert it into human readable ascii text. It does this by | ||
3534 | * calling the @p dumpfunc callback for all new text that is | ||
3535 | * generated. This callback should append to any existing text | ||
3536 | * buffer and will be passed the pointer @p dumpdata as a parameter | ||
3537 | * as well as a string with new text to be appended. | ||
3538 | * | ||
3539 | * @see eet_data_dump() | ||
3540 | * | ||
3541 | * @since 1.0.0 | ||
3542 | * @ingroup Eet_Data_Cipher_Group | ||
3543 | */ | ||
3544 | EAPI int | ||
3545 | eet_data_dump_cipher(Eet_File *ef, | ||
3546 | const char *name, | ||
3547 | const char *cipher_key, | ||
3548 | Eet_Dump_Callback dumpfunc, | ||
3549 | void *dumpdata); | ||
3550 | |||
3551 | /** | ||
3552 | * Take an ascii encoding from eet_data_dump() and re-encode in | ||
3553 | * binary using a cipher. | ||
3554 | * @param ef A valid eet file handle. | ||
3555 | * @param name Name of the entry. eg: "/base/file_i_want". | ||
3556 | * @param cipher_key The key to use as cipher. | ||
3557 | * @param text The pointer to the string data to parse and encode. | ||
3558 | * @param textlen The size of the string in bytes (not including 0 | ||
3559 | * byte terminator). | ||
3560 | * @param compress Compression flags (1 == compress, 0 = don't compress). | ||
3561 | * @return 1 on success, 0 on failure | ||
3562 | * | ||
3563 | * This function will parse the string pointed to by @p text, | ||
3564 | * encode it the same way eet_data_descriptor_encode() takes an | ||
3565 | * in-memory data struct and encodes into a binary blob. | ||
3566 | * | ||
3567 | * The data (optionally compressed) will be in ram, pending a flush to | ||
3568 | * disk (it will stay in ram till the eet file handle is closed though). | ||
3569 | * | ||
3570 | * @see eet_data_undump() | ||
3571 | * | ||
3572 | * @since 1.0.0 | ||
3573 | * @ingroup Eet_Data_Cipher_Group | ||
3574 | */ | ||
3575 | EAPI int | ||
3576 | eet_data_undump_cipher(Eet_File *ef, | ||
3577 | const char *name, | ||
3578 | const char *cipher_key, | ||
3579 | const char *text, | ||
3580 | int textlen, | ||
3581 | int compress); | ||
3582 | |||
3583 | /** | ||
3584 | * Decode a data structure from an arbitrary location in memory | ||
3585 | * using a cipher. | ||
3586 | * @param edd The data descriptor to use when decoding. | ||
3587 | * @param data_in The pointer to the data to decode into a struct. | ||
3588 | * @param cipher_key The key to use as cipher. | ||
3589 | * @param size_in The size of the data pointed to in bytes. | ||
3590 | * @return NULL on failure, or a valid decoded struct pointer on success. | ||
3591 | * | ||
3592 | * This function will decode a data structure that has been encoded using | ||
3593 | * eet_data_descriptor_encode(), and return a data structure with all its | ||
3594 | * elements filled out, if successful, or NULL on failure. | ||
3595 | * | ||
3596 | * The data to be decoded is stored at the memory pointed to by @p data_in, | ||
3597 | * and is described by the descriptor pointed to by @p edd. The data size is | ||
3598 | * passed in as the value to @p size_in, ande must be greater than 0 to | ||
3599 | * succeed. | ||
3600 | * | ||
3601 | * This function is useful for decoding data structures delivered to the | ||
3602 | * application by means other than an eet file, such as an IPC or socket | ||
3603 | * connection, raw files, shared memory etc. | ||
3604 | * | ||
3605 | * Please see eet_data_read() for more information. | ||
3606 | * | ||
3607 | * @see eet_data_descriptor_decode() | ||
3608 | * | ||
3609 | * @since 1.0.0 | ||
3610 | * @ingroup Eet_Data_Cipher_Group | ||
3611 | */ | ||
3612 | EAPI void * | ||
3613 | eet_data_descriptor_decode_cipher(Eet_Data_Descriptor *edd, | ||
3614 | const void *data_in, | ||
3615 | const char *cipher_key, | ||
3616 | int size_in); | ||
3617 | |||
3618 | /** | ||
3619 | * Encode a data struct to memory and return that encoded data | ||
3620 | * using a cipher. | ||
3621 | * @param edd The data descriptor to use when encoding. | ||
3622 | * @param data_in The pointer to the struct to encode into data. | ||
3623 | * @param cipher_key The key to use as cipher. | ||
3624 | * @param size_ret pointer to the an int to be filled with the decoded size. | ||
3625 | * @return NULL on failure, or a valid encoded data chunk on success. | ||
3626 | * | ||
3627 | * This function takes a data structutre in memory and encodes it into a | ||
3628 | * serialised chunk of data that can be decoded again by | ||
3629 | * eet_data_descriptor_decode(). This is useful for being able to transmit | ||
3630 | * data structures across sockets, pipes, IPC or shared file mechanisms, | ||
3631 | * without having to worry about memory space, machine type, endianess etc. | ||
3632 | * | ||
3633 | * The parameter @p edd must point to a valid data descriptor, and | ||
3634 | * @p data_in must point to the right data structure to encode. If not, the | ||
3635 | * encoding may fail. | ||
3636 | * | ||
3637 | * On success a non NULL valid pointer is returned and what @p size_ret | ||
3638 | * points to is set to the size of this decoded data, in bytes. When the | ||
3639 | * encoded data is no longer needed, call free() on it. On failure NULL is | ||
3640 | * returned and what @p size_ret points to is set to 0. | ||
3641 | * | ||
3642 | * Please see eet_data_write() for more information. | ||
3643 | * | ||
3644 | * @see eet_data_descriptor_encode() | ||
3645 | * | ||
3646 | * @since 1.0.0 | ||
3647 | * @ingroup Eet_Data_Cipher_Group | ||
3648 | */ | ||
3649 | EAPI void * | ||
3650 | eet_data_descriptor_encode_cipher(Eet_Data_Descriptor *edd, | ||
3651 | const void *data_in, | ||
3652 | const char *cipher_key, | ||
3653 | int *size_ret); | ||
3654 | |||
3655 | /** | ||
3656 | * @defgroup Eet_Node_Group Low-level Serialization Structures. | ||
3657 | * | ||
3658 | * Functions that create, destroy and manipulate serialization nodes | ||
3659 | * used by @ref Eet_Data_Group. | ||
3660 | * | ||
3661 | * @{ | ||
3662 | */ | ||
3663 | |||
3664 | /** | ||
3665 | * @typedef Eet_Node | ||
3666 | * Opaque handle to manage serialization node. | ||
3667 | */ | ||
3668 | typedef struct _Eet_Node Eet_Node; | ||
3669 | |||
3670 | /** | ||
3671 | * @typedef Eet_Node_Data | ||
3672 | * Contains an union that can fit any kind of node. | ||
3673 | */ | ||
3674 | typedef struct _Eet_Node_Data Eet_Node_Data; | ||
3675 | |||
3676 | /** | ||
3677 | * @struct _Eet_Node_Data | ||
3678 | * Contains an union that can fit any kind of node. | ||
3679 | */ | ||
3680 | struct _Eet_Node_Data | ||
3681 | { | ||
3682 | union { | ||
3683 | char c; | ||
3684 | short s; | ||
3685 | int i; | ||
3686 | long long l; | ||
3687 | float f; | ||
3688 | double d; | ||
3689 | unsigned char uc; | ||
3690 | unsigned short us; | ||
3691 | unsigned int ui; | ||
3692 | unsigned long long ul; | ||
3693 | const char *str; | ||
3694 | } value; | ||
3695 | }; | ||
3696 | |||
3697 | /** | ||
3698 | * @} | ||
3699 | */ | ||
3700 | |||
3701 | /** | ||
3702 | * TODO FIX ME | ||
3703 | * @ingroup Eet_Node_Group | ||
3704 | */ | ||
3705 | EAPI Eet_Node * | ||
3706 | eet_node_char_new(const char *name, | ||
3707 | char c); | ||
3708 | |||
3709 | /** | ||
3710 | * TODO FIX ME | ||
3711 | * @ingroup Eet_Node_Group | ||
3712 | */ | ||
3713 | EAPI Eet_Node * | ||
3714 | eet_node_short_new(const char *name, | ||
3715 | short s); | ||
3716 | |||
3717 | /** | ||
3718 | * TODO FIX ME | ||
3719 | * @ingroup Eet_Node_Group | ||
3720 | */ | ||
3721 | EAPI Eet_Node * | ||
3722 | eet_node_int_new(const char *name, | ||
3723 | int i); | ||
3724 | |||
3725 | /** | ||
3726 | * TODO FIX ME | ||
3727 | * @ingroup Eet_Node_Group | ||
3728 | */ | ||
3729 | EAPI Eet_Node * | ||
3730 | eet_node_long_long_new(const char *name, | ||
3731 | long long l); | ||
3732 | |||
3733 | /** | ||
3734 | * TODO FIX ME | ||
3735 | * @ingroup Eet_Node_Group | ||
3736 | */ | ||
3737 | EAPI Eet_Node * | ||
3738 | eet_node_float_new(const char *name, | ||
3739 | float f); | ||
3740 | |||
3741 | /** | ||
3742 | * TODO FIX ME | ||
3743 | * @ingroup Eet_Node_Group | ||
3744 | */ | ||
3745 | EAPI Eet_Node * | ||
3746 | eet_node_double_new(const char *name, | ||
3747 | double d); | ||
3748 | |||
3749 | /** | ||
3750 | * TODO FIX ME | ||
3751 | * @ingroup Eet_Node_Group | ||
3752 | */ | ||
3753 | EAPI Eet_Node * | ||
3754 | eet_node_unsigned_char_new(const char *name, | ||
3755 | unsigned char uc); | ||
3756 | |||
3757 | /** | ||
3758 | * TODO FIX ME | ||
3759 | * @ingroup Eet_Node_Group | ||
3760 | */ | ||
3761 | EAPI Eet_Node * | ||
3762 | eet_node_unsigned_short_new(const char *name, | ||
3763 | unsigned short us); | ||
3764 | |||
3765 | /** | ||
3766 | * TODO FIX ME | ||
3767 | * @ingroup Eet_Node_Group | ||
3768 | */ | ||
3769 | EAPI Eet_Node * | ||
3770 | eet_node_unsigned_int_new(const char *name, | ||
3771 | unsigned int ui); | ||
3772 | |||
3773 | /** | ||
3774 | * TODO FIX ME | ||
3775 | * @ingroup Eet_Node_Group | ||
3776 | */ | ||
3777 | EAPI Eet_Node * | ||
3778 | eet_node_unsigned_long_long_new(const char *name, | ||
3779 | unsigned long long l); | ||
3780 | |||
3781 | /** | ||
3782 | * TODO FIX ME | ||
3783 | * @ingroup Eet_Node_Group | ||
3784 | */ | ||
3785 | EAPI Eet_Node * | ||
3786 | eet_node_string_new(const char *name, | ||
3787 | const char *str); | ||
3788 | |||
3789 | /** | ||
3790 | * TODO FIX ME | ||
3791 | * @ingroup Eet_Node_Group | ||
3792 | */ | ||
3793 | EAPI Eet_Node * | ||
3794 | eet_node_inlined_string_new(const char *name, | ||
3795 | const char *str); | ||
3796 | |||
3797 | /** | ||
3798 | * TODO FIX ME | ||
3799 | * @ingroup Eet_Node_Group | ||
3800 | */ | ||
3801 | EAPI Eet_Node * | ||
3802 | eet_node_null_new(const char *name); | ||
3803 | |||
3804 | /** | ||
3805 | * TODO FIX ME | ||
3806 | * @ingroup Eet_Node_Group | ||
3807 | */ | ||
3808 | EAPI Eet_Node * | ||
3809 | eet_node_list_new(const char *name, | ||
3810 | Eina_List *nodes); | ||
3811 | |||
3812 | /** | ||
3813 | * TODO FIX ME | ||
3814 | * @ingroup Eet_Node_Group | ||
3815 | */ | ||
3816 | EAPI Eet_Node * | ||
3817 | eet_node_array_new(const char *name, | ||
3818 | int count, | ||
3819 | Eina_List *nodes); | ||
3820 | |||
3821 | /** | ||
3822 | * TODO FIX ME | ||
3823 | * @ingroup Eet_Node_Group | ||
3824 | */ | ||
3825 | EAPI Eet_Node * | ||
3826 | eet_node_var_array_new(const char *name, | ||
3827 | Eina_List *nodes); | ||
3828 | |||
3829 | /** | ||
3830 | * TODO FIX ME | ||
3831 | * @ingroup Eet_Node_Group | ||
3832 | */ | ||
3833 | EAPI Eet_Node * | ||
3834 | eet_node_hash_new(const char *name, | ||
3835 | const char *key, | ||
3836 | Eet_Node *node); | ||
3837 | |||
3838 | /** | ||
3839 | * TODO FIX ME | ||
3840 | * @ingroup Eet_Node_Group | ||
3841 | */ | ||
3842 | EAPI Eet_Node * | ||
3843 | eet_node_struct_new(const char *name, | ||
3844 | Eina_List *nodes); | ||
3845 | |||
3846 | /** | ||
3847 | * TODO FIX ME | ||
3848 | * @ingroup Eet_Node_Group | ||
3849 | */ | ||
3850 | EAPI Eet_Node * | ||
3851 | eet_node_struct_child_new(const char *parent, | ||
3852 | Eet_Node *child); | ||
3853 | |||
3854 | /** | ||
3855 | * @brief Get a node's child nodes | ||
3856 | * @param node The node | ||
3857 | * @return The first child node which contains a pointer to the | ||
3858 | * next child node and the parent. | ||
3859 | * @since 1.5 | ||
3860 | */ | ||
3861 | EAPI Eet_Node * | ||
3862 | eet_node_children_get(Eet_Node *node); | ||
3863 | |||
3864 | /** | ||
3865 | * @brief Get the next node in a list of nodes | ||
3866 | * @param node The node | ||
3867 | * @return A node which contains a pointer to the | ||
3868 | * next child node and the parent. | ||
3869 | * @since 1.5 | ||
3870 | */ | ||
3871 | EAPI Eet_Node * | ||
3872 | eet_node_next_get(Eet_Node *node); | ||
3873 | |||
3874 | /** | ||
3875 | * @brief Get the parent node of a node | ||
3876 | * @param node The node | ||
3877 | * @return The parent node of @p node | ||
3878 | * @since 1.5 | ||
3879 | */ | ||
3880 | EAPI Eet_Node * | ||
3881 | eet_node_parent_get(Eet_Node *node); | ||
3882 | |||
3883 | /** | ||
3884 | * TODO FIX ME | ||
3885 | * @ingroup Eet_Node_Group | ||
3886 | */ | ||
3887 | EAPI void | ||
3888 | eet_node_list_append(Eet_Node *parent, | ||
3889 | const char *name, | ||
3890 | Eet_Node *child); | ||
3891 | |||
3892 | /** | ||
3893 | * TODO FIX ME | ||
3894 | * @ingroup Eet_Node_Group | ||
3895 | */ | ||
3896 | EAPI void | ||
3897 | eet_node_struct_append(Eet_Node *parent, | ||
3898 | const char *name, | ||
3899 | Eet_Node *child); | ||
3900 | |||
3901 | /** | ||
3902 | * TODO FIX ME | ||
3903 | * @ingroup Eet_Node_Group | ||
3904 | */ | ||
3905 | EAPI void | ||
3906 | eet_node_hash_add(Eet_Node *parent, | ||
3907 | const char *name, | ||
3908 | const char *key, | ||
3909 | Eet_Node *child); | ||
3910 | |||
3911 | /** | ||
3912 | * TODO FIX ME | ||
3913 | * @ingroup Eet_Node_Group | ||
3914 | */ | ||
3915 | EAPI void | ||
3916 | eet_node_dump(Eet_Node *n, | ||
3917 | int dumplevel, | ||
3918 | Eet_Dump_Callback dumpfunc, | ||
3919 | void *dumpdata); | ||
3920 | |||
3921 | /** | ||
3922 | * @brief Return the type of a node | ||
3923 | * @param node The node | ||
3924 | * @return The node's type (EET_T_$TYPE) | ||
3925 | * @since 1.5 | ||
3926 | */ | ||
3927 | EAPI int | ||
3928 | eet_node_type_get(Eet_Node *node); | ||
3929 | |||
3930 | /** | ||
3931 | * @brief Return the node's data | ||
3932 | * @param node The node | ||
3933 | * @return The data contained in the node | ||
3934 | * @since 1.5 | ||
3935 | */ | ||
3936 | EAPI Eet_Node_Data * | ||
3937 | eet_node_value_get(Eet_Node *node); | ||
3938 | |||
3939 | /** | ||
3940 | * TODO FIX ME | ||
3941 | * @ingroup Eet_Node_Group | ||
3942 | */ | ||
3943 | EAPI void | ||
3944 | eet_node_del(Eet_Node *n); | ||
3945 | |||
3946 | /** | ||
3947 | * TODO FIX ME | ||
3948 | * @ingroup Eet_Node_Group | ||
3949 | */ | ||
3950 | EAPI void * | ||
3951 | eet_data_node_encode_cipher(Eet_Node *node, | ||
3952 | const char *cipher_key, | ||
3953 | int *size_ret); | ||
3954 | |||
3955 | /** | ||
3956 | * TODO FIX ME | ||
3957 | * @ingroup Eet_Node_Group | ||
3958 | */ | ||
3959 | EAPI Eet_Node * | ||
3960 | eet_data_node_decode_cipher(const void *data_in, | ||
3961 | const char *cipher_key, | ||
3962 | int size_in); | ||
3963 | |||
3964 | /** | ||
3965 | * TODO FIX ME | ||
3966 | * @ingroup Eet_Node_Group | ||
3967 | */ | ||
3968 | EAPI Eet_Node * | ||
3969 | eet_data_node_read_cipher(Eet_File *ef, | ||
3970 | const char *name, | ||
3971 | const char *cipher_key); | ||
3972 | |||
3973 | /** | ||
3974 | * TODO FIX ME | ||
3975 | * @ingroup Eet_Node_Group | ||
3976 | */ | ||
3977 | EAPI int | ||
3978 | eet_data_node_write_cipher(Eet_File *ef, | ||
3979 | const char *name, | ||
3980 | const char *cipher_key, | ||
3981 | Eet_Node *node, | ||
3982 | int compress); | ||
3983 | |||
3984 | /* EXPERIMENTAL: THIS API MAY CHANGE IN THE FUTURE, USE IT ONLY IF YOU KNOW WHAT YOU ARE DOING. */ | ||
3985 | |||
3986 | /** | ||
3987 | * @typedef Eet_Node_Walk | ||
3988 | * Describes how to walk trees of #Eet_Node. | ||
3989 | */ | ||
3990 | typedef struct _Eet_Node_Walk Eet_Node_Walk; | ||
3991 | |||
3992 | typedef void * (*Eet_Node_Walk_Struct_Alloc_Callback)(const char *type, void *user_data); | ||
3993 | typedef void (*Eet_Node_Walk_Struct_Add_Callback)(void *parent, const char *name, void *child, void *user_data); | ||
3994 | typedef void * (*Eet_Node_Walk_Array_Callback)(Eina_Bool variable, const char *name, int count, void *user_data); | ||
3995 | typedef void (*Eet_Node_Walk_Insert_Callback)(void *array, int index, void *child, void *user_data); | ||
3996 | typedef void * (*Eet_Node_Walk_List_Callback)(const char *name, void *user_data); | ||
3997 | typedef void (*Eet_Node_Walk_Append_Callback)(void *list, void *child, void *user_data); | ||
3998 | typedef void * (*Eet_Node_Walk_Hash_Callback)(void *parent, const char *name, const char *key, void *value, void *user_data); | ||
3999 | typedef void * (*Eet_Node_Walk_Simple_Callback)(int type, Eet_Node_Data *data, void *user_data); | ||
4000 | |||
4001 | /** | ||
4002 | * @struct _Eet_Node_Walk | ||
4003 | * Describes how to walk trees of #Eet_Node. | ||
4004 | */ | ||
4005 | struct _Eet_Node_Walk | ||
4006 | { | ||
4007 | Eet_Node_Walk_Struct_Alloc_Callback struct_alloc; | ||
4008 | Eet_Node_Walk_Struct_Add_Callback struct_add; | ||
4009 | Eet_Node_Walk_Array_Callback array; | ||
4010 | Eet_Node_Walk_Insert_Callback insert; | ||
4011 | Eet_Node_Walk_List_Callback list; | ||
4012 | Eet_Node_Walk_Append_Callback append; | ||
4013 | Eet_Node_Walk_Hash_Callback hash; | ||
4014 | Eet_Node_Walk_Simple_Callback simple; | ||
4015 | }; | ||
4016 | |||
4017 | EAPI void * | ||
4018 | eet_node_walk(void *parent, | ||
4019 | const char *name, | ||
4020 | Eet_Node *root, | ||
4021 | Eet_Node_Walk *cb, | ||
4022 | void *user_data); | ||
4023 | |||
4024 | /*******/ | ||
4025 | |||
4026 | /** | ||
4027 | * @defgroup Eet_Connection_Group Helper function to use eet over a network link | ||
4028 | * | ||
4029 | * Function that reconstruct and prepare packet of @ref Eet_Data_Group to be send. | ||
4030 | * | ||
4031 | */ | ||
4032 | |||
4033 | /** | ||
4034 | * @typedef Eet_Connection | ||
4035 | * Opaque handle to track paquet for a specific connection. | ||
4036 | * | ||
4037 | * @ingroup Eet_Connection_Group | ||
4038 | */ | ||
4039 | typedef struct _Eet_Connection Eet_Connection; | ||
4040 | |||
4041 | /** | ||
4042 | * @typedef Eet_Read_Cb | ||
4043 | * Called back when an @ref Eet_Data_Group has been received completly and could be used. | ||
4044 | * | ||
4045 | * @ingroup Eet_Connection_Group | ||
4046 | */ | ||
4047 | typedef Eina_Bool Eet_Read_Cb (const void *eet_data, size_t size, void *user_data); | ||
4048 | |||
4049 | /** | ||
4050 | * @typedef Eet_Write_Cb | ||
4051 | * Called back when a packet containing @ref Eet_Data_Group data is ready to be send. | ||
4052 | * | ||
4053 | * @ingroup Eet_Connection_Group | ||
4054 | */ | ||
4055 | typedef Eina_Bool Eet_Write_Cb (const void *data, size_t size, void *user_data); | ||
4056 | |||
4057 | /** | ||
4058 | * Instanciate a new connection to track. | ||
4059 | * @param eet_read_cb Function to call when one Eet_Data packet has been fully assemble. | ||
4060 | * @param eet_write_cb Function to call when one Eet_Data packet is ready to be send over the wire. | ||
4061 | * @param user_data Pointer provided to both functions to be used as a context handler. | ||
4062 | * @return NULL on failure, or a valid Eet_Connection handler. | ||
4063 | * | ||
4064 | * For every connection to track you will need a separate Eet_Connection provider. | ||
4065 | * | ||
4066 | * @since 1.2.4 | ||
4067 | * @ingroup Eet_Connection_Group | ||
4068 | */ | ||
4069 | EAPI Eet_Connection * | ||
4070 | eet_connection_new(Eet_Read_Cb *eet_read_cb, | ||
4071 | Eet_Write_Cb *eet_write_cb, | ||
4072 | const void *user_data); | ||
4073 | |||
4074 | /** | ||
4075 | * Process a raw packet received over the link | ||
4076 | * @param conn Connection handler to track. | ||
4077 | * @param data Raw data packet. | ||
4078 | * @param size The size of that packet. | ||
4079 | * @return 0 on complete success, any other value indicate where in the stream it got wrong (It could be before that packet). | ||
4080 | * | ||
4081 | * Every time you receive a packet related to your connection, you should pass | ||
4082 | * it to that function so that it could process and assemble packet has you | ||
4083 | * receive it. It will automatically call Eet_Read_Cb when one is fully received. | ||
4084 | * | ||
4085 | * @since 1.2.4 | ||
4086 | * @ingroup Eet_Connection_Group | ||
4087 | */ | ||
4088 | EAPI int | ||
4089 | eet_connection_received(Eet_Connection *conn, | ||
4090 | const void *data, | ||
4091 | size_t size); | ||
4092 | |||
4093 | /** | ||
4094 | * Convert a complex structure and prepare it to be send. | ||
4095 | * @param conn Connection handler to track. | ||
4096 | * @param edd The data descriptor to use when encoding. | ||
4097 | * @param data_in The pointer to the struct to encode into data. | ||
4098 | * @param cipher_key The key to use as cipher. | ||
4099 | * @return EINA_TRUE if the data where correctly send, EINA_FALSE if they don't. | ||
4100 | * | ||
4101 | * This function serialize data_in with edd, assemble the packet and call | ||
4102 | * Eet_Write_Cb when ready. The data passed Eet_Write_Cb are temporary allocated | ||
4103 | * and will vanish just after the return of the callback. | ||
4104 | * | ||
4105 | * @see eet_data_descriptor_encode_cipher | ||
4106 | * | ||
4107 | * @since 1.2.4 | ||
4108 | * @ingroup Eet_Connection_Group | ||
4109 | */ | ||
4110 | EAPI Eina_Bool | ||
4111 | eet_connection_send(Eet_Connection *conn, | ||
4112 | Eet_Data_Descriptor *edd, | ||
4113 | const void *data_in, | ||
4114 | const char *cipher_key); | ||
4115 | |||
4116 | /** | ||
4117 | * Convert a Eet_Node tree and prepare it to be send. | ||
4118 | * @param conn Connection handler to track. | ||
4119 | * @param node The data tree to use when encoding. | ||
4120 | * @param cipher_key The key to use as cipher. | ||
4121 | * @return EINA_TRUE if the data where correctly send, EINA_FALSE if they don't. | ||
4122 | * | ||
4123 | * This function serialize node, assemble the packet and call | ||
4124 | * Eet_Write_Cb when ready. The data passed Eet_Write_Cb are temporary allocated | ||
4125 | * and will vanish just after the return of the callback. | ||
4126 | * | ||
4127 | * @see eet_data_node_encode_cipher | ||
4128 | * | ||
4129 | * @since 1.2.4 | ||
4130 | * @ingroup Eet_Connection_Group | ||
4131 | */ | ||
4132 | EAPI Eina_Bool | ||
4133 | eet_connection_node_send(Eet_Connection *conn, | ||
4134 | Eet_Node *node, | ||
4135 | const char *cipher_key); | ||
4136 | |||
4137 | /** | ||
4138 | * Close a connection and lost its track. | ||
4139 | * @param conn Connection handler to close. | ||
4140 | * @param on_going Signal if a partial packet wasn't completed. | ||
4141 | * @return the user_data passed to both callback. | ||
4142 | * | ||
4143 | * @since 1.2.4 | ||
4144 | * @ingroup Eet_Connection_Group | ||
4145 | */ | ||
4146 | EAPI void * | ||
4147 | eet_connection_close(Eet_Connection *conn, | ||
4148 | Eina_Bool *on_going); | ||
4149 | |||
4150 | /***************************************************************************/ | ||
4151 | |||
4152 | #ifdef __cplusplus | ||
4153 | } | ||
4154 | #endif /* ifdef __cplusplus */ | ||
4155 | |||
4156 | #endif /* ifndef _EET_H */ | ||
diff --git a/libraries/eet/src/lib/Eet_private.h b/libraries/eet/src/lib/Eet_private.h new file mode 100644 index 0000000..83f4c18 --- /dev/null +++ b/libraries/eet/src/lib/Eet_private.h | |||
@@ -0,0 +1,191 @@ | |||
1 | #ifndef _EET_PRIVATE_H | ||
2 | #define _EET_PRIVATE_H | ||
3 | |||
4 | #include <Eina.h> | ||
5 | |||
6 | typedef enum _Eet_Convert_Type Eet_Convert_Type; | ||
7 | |||
8 | enum _Eet_Convert_Type | ||
9 | { | ||
10 | EET_D_NOTHING = 0, | ||
11 | EET_D_FLOAT = 1 << 1, | ||
12 | EET_D_DOUBLE = 1 << 2, | ||
13 | EET_D_FIXED_POINT = 1 << 4 | ||
14 | }; | ||
15 | |||
16 | typedef struct _Eet_String Eet_String; | ||
17 | typedef struct _Eet_Convert Eet_Convert; | ||
18 | |||
19 | struct _Eet_Convert | ||
20 | { | ||
21 | float f; | ||
22 | double d; | ||
23 | Eina_F32p32 fp; | ||
24 | |||
25 | Eet_Convert_Type type; | ||
26 | }; | ||
27 | |||
28 | struct _Eet_String | ||
29 | { | ||
30 | const char *str; | ||
31 | |||
32 | int len; | ||
33 | |||
34 | int next; | ||
35 | int prev; | ||
36 | |||
37 | unsigned char hash; | ||
38 | unsigned char allocated : 1; | ||
39 | }; | ||
40 | struct _Eet_Dictionary | ||
41 | { | ||
42 | Eet_String *all; | ||
43 | Eina_Hash *converts; | ||
44 | |||
45 | int size; | ||
46 | int offset; | ||
47 | |||
48 | int hash[256]; | ||
49 | |||
50 | int count; | ||
51 | int total; | ||
52 | |||
53 | const char *start; | ||
54 | const char *end; | ||
55 | }; | ||
56 | |||
57 | struct _Eet_Node | ||
58 | { | ||
59 | int type; | ||
60 | int count; | ||
61 | const char *name; | ||
62 | const char *key; | ||
63 | Eet_Node *values; | ||
64 | Eet_Node *next; | ||
65 | Eet_Node *parent; | ||
66 | Eet_Node_Data data; | ||
67 | }; | ||
68 | |||
69 | /* | ||
70 | * variable and macros used for the eina_log module | ||
71 | */ | ||
72 | extern int _eet_log_dom_global; | ||
73 | |||
74 | /* | ||
75 | * Macros that are used everywhere | ||
76 | * | ||
77 | * the first four macros are the general macros for the lib | ||
78 | */ | ||
79 | #ifdef EET_DEFAULT_LOG_COLOR | ||
80 | # undef EET_DEFAULT_LOG_COLOR | ||
81 | #endif /* ifdef EET_DEFAULT_LOG_COLOR */ | ||
82 | #define EET_DEFAULT_LOG_COLOR EINA_COLOR_CYAN | ||
83 | #ifdef ERR | ||
84 | # undef ERR | ||
85 | #endif /* ifdef ERR */ | ||
86 | #define ERR(...) EINA_LOG_DOM_ERR(_eet_log_dom_global, __VA_ARGS__) | ||
87 | #ifdef DBG | ||
88 | # undef DBG | ||
89 | #endif /* ifdef DBG */ | ||
90 | #define DBG(...) EINA_LOG_DOM_DBG(_eet_log_dom_global, __VA_ARGS__) | ||
91 | #ifdef INF | ||
92 | # undef INF | ||
93 | #endif /* ifdef INF */ | ||
94 | #define INF(...) EINA_LOG_DOM_INFO(_eet_log_dom_global, __VA_ARGS__) | ||
95 | #ifdef WRN | ||
96 | # undef WRN | ||
97 | #endif /* ifdef WRN */ | ||
98 | #define WRN(...) EINA_LOG_DOM_WARN(_eet_log_dom_global, __VA_ARGS__) | ||
99 | #ifdef CRIT | ||
100 | # undef CRIT | ||
101 | #endif /* ifdef CRIT */ | ||
102 | #define CRIT(...) EINA_LOG_DOM_CRIT(_eet_log_dom_global, __VA_ARGS__) | ||
103 | |||
104 | Eet_Dictionary * | ||
105 | eet_dictionary_add(void); | ||
106 | void | ||
107 | eet_dictionary_free(Eet_Dictionary *ed); | ||
108 | int | ||
109 | eet_dictionary_string_add(Eet_Dictionary *ed, | ||
110 | const char *string); | ||
111 | int | ||
112 | eet_dictionary_string_get_size(const Eet_Dictionary *ed, | ||
113 | int index); | ||
114 | const char * | ||
115 | eet_dictionary_string_get_char(const Eet_Dictionary *ed, | ||
116 | int index); | ||
117 | Eina_Bool | ||
118 | eet_dictionary_string_get_float(const Eet_Dictionary *ed, | ||
119 | int index, | ||
120 | float *result); | ||
121 | Eina_Bool | ||
122 | eet_dictionary_string_get_double(const Eet_Dictionary *ed, | ||
123 | int index, | ||
124 | double *result); | ||
125 | Eina_Bool | ||
126 | eet_dictionary_string_get_fp(const Eet_Dictionary *ed, | ||
127 | int index, | ||
128 | Eina_F32p32 *result); | ||
129 | int | ||
130 | eet_dictionary_string_get_hash(const Eet_Dictionary *ed, | ||
131 | int index); | ||
132 | |||
133 | int _eet_hash_gen(const char *key, | ||
134 | int hash_size); | ||
135 | |||
136 | const void * | ||
137 | eet_identity_check(const void *data_base, | ||
138 | unsigned int data_length, | ||
139 | void **sha1, | ||
140 | int *sha1_length, | ||
141 | const void *signature_base, | ||
142 | unsigned int signature_length, | ||
143 | const void **raw_signature_base, | ||
144 | unsigned int *raw_signature_length, | ||
145 | int *x509_length); | ||
146 | void * | ||
147 | eet_identity_compute_sha1(const void *data_base, | ||
148 | unsigned int data_length, | ||
149 | int *sha1_length); | ||
150 | Eet_Error | ||
151 | eet_cipher(const void *data, | ||
152 | unsigned int size, | ||
153 | const char *key, | ||
154 | unsigned int length, | ||
155 | void **result, | ||
156 | unsigned int *result_length); | ||
157 | Eet_Error | ||
158 | eet_decipher(const void *data, | ||
159 | unsigned int size, | ||
160 | const char *key, | ||
161 | unsigned int length, | ||
162 | void **result, | ||
163 | unsigned int *result_length); | ||
164 | Eet_Error | ||
165 | eet_identity_sign(FILE *fp, | ||
166 | Eet_Key *key); | ||
167 | void | ||
168 | eet_identity_unref(Eet_Key *key); | ||
169 | void | ||
170 | eet_identity_ref(Eet_Key *key); | ||
171 | |||
172 | void | ||
173 | eet_node_shutdown(void); | ||
174 | int | ||
175 | eet_node_init(void); | ||
176 | Eet_Node * | ||
177 | eet_node_new(void); | ||
178 | void | ||
179 | eet_node_free(Eet_Node *node); | ||
180 | |||
181 | #ifndef PATH_MAX | ||
182 | # define PATH_MAX 4096 | ||
183 | #endif /* ifndef PATH_MAX */ | ||
184 | |||
185 | #ifdef DNDEBUG | ||
186 | # define EET_ASSERT(Test, Do) if (Test == 0) {Do; } | ||
187 | #else /* ifdef DNDEBUG */ | ||
188 | # define EET_ASSERT(Test, Do) if (Test == 0) {abort(); } | ||
189 | #endif /* ifdef DNDEBUG */ | ||
190 | |||
191 | #endif /* ifndef _EET_PRIVATE_H */ | ||
diff --git a/libraries/eet/src/lib/Makefile.am b/libraries/eet/src/lib/Makefile.am new file mode 100644 index 0000000..4633749 --- /dev/null +++ b/libraries/eet/src/lib/Makefile.am | |||
@@ -0,0 +1,162 @@ | |||
1 | |||
2 | MAINTAINERCLEANFILES = Makefile.in | ||
3 | |||
4 | AM_CPPFLAGS = \ | ||
5 | -I. \ | ||
6 | -I$(top_srcdir)/src/lib \ | ||
7 | -I$(top_builddir)/src/lib \ | ||
8 | -DPACKAGE_BIN_DIR=\"$(bindir)\" \ | ||
9 | -DPACKAGE_LIB_DIR=\"$(libdir)\" \ | ||
10 | -DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ | ||
11 | @EVIL_CFLAGS@ \ | ||
12 | @EINA_CFLAGS@ \ | ||
13 | @EET_CPPFLAGS@ \ | ||
14 | @EFL_EET_BUILD@ \ | ||
15 | @EFL_COVERAGE_CFLAGS@ \ | ||
16 | @OPENSSL_CFLAGS@ \ | ||
17 | @GNUTLS_CFLAGS@ | ||
18 | |||
19 | includes_HEADERS = Eet.h | ||
20 | includesdir = $(includedir)/eet-@VMAJ@ | ||
21 | |||
22 | lib_LTLIBRARIES = libeet.la | ||
23 | |||
24 | base_sources = \ | ||
25 | eet_lib.c \ | ||
26 | eet_data.c \ | ||
27 | eet_image.c \ | ||
28 | eet_cipher.c \ | ||
29 | eet_dictionary.c \ | ||
30 | eet_node.c \ | ||
31 | eet_utils.c \ | ||
32 | eet_connection.c | ||
33 | |||
34 | if EET_AMALGAMATION | ||
35 | nodist_libeet_la_SOURCES = eet_amalgamation.c | ||
36 | |||
37 | eet_amalgamation.c: $(base_sources) Makefile | ||
38 | -rm -f eet_amalgamation.c | ||
39 | |||
40 | @echo "#ifdef HAVE_CONFIG_H" >> eet_amalgamation.c | ||
41 | @echo "# include \"config.h\"" >> eet_amalgamation.c | ||
42 | @echo "#endif" >> eet_amalgamation.c | ||
43 | |||
44 | @echo "#ifdef HAVE_ALLOCA_H" >> eet_amalgamation.c | ||
45 | @echo "# include <alloca.h>" >> eet_amalgamation.c | ||
46 | @echo "#elif defined __GNUC__" >> eet_amalgamation.c | ||
47 | @echo "# define alloca __builtin_alloca" >> eet_amalgamation.c | ||
48 | @echo "#elif defined _AIX" >> eet_amalgamation.c | ||
49 | @echo "# define alloca __alloca" >> eet_amalgamation.c | ||
50 | @echo "#elif defined _MSC_VER" >> eet_amalgamation.c | ||
51 | @echo "# include <malloc.h>" >> eet_amalgamation.c | ||
52 | @echo "# define alloca _alloca" >> eet_amalgamation.c | ||
53 | @echo "#else" >> eet_amalgamation.c | ||
54 | @echo "# include <stddef.h>" >> eet_amalgamation.c | ||
55 | @echo "# ifdef __cplusplus" >> eet_amalgamation.c | ||
56 | @echo "#extern \"C\"" >> eet_amalgamation.c | ||
57 | @echo "# endif" >> eet_amalgamation.c | ||
58 | @echo "#void *alloca (size_t);" >> eet_amalgamation.c | ||
59 | @echo "#endif" >> eet_amalgamation.c | ||
60 | |||
61 | @echo "#include <stdio.h>" >> eet_amalgamation.c | ||
62 | @echo "#include <string.h>" >> eet_amalgamation.c | ||
63 | @echo "#include <math.h>" >> eet_amalgamation.c | ||
64 | @echo "#include <ctype.h>" >> eet_amalgamation.c | ||
65 | @echo "#include <limits.h>" >> eet_amalgamation.c | ||
66 | @echo "#include <sys/types.h>" >> eet_amalgamation.c | ||
67 | @echo "#include <sys/stat.h>" >> eet_amalgamation.c | ||
68 | @echo "#ifdef HAVE_SIGNATURE" >> eet_amalgamation.c | ||
69 | @echo "# include <sys/mman.h>" >> eet_amalgamation.c | ||
70 | @echo "#endif" >> eet_amalgamation.c | ||
71 | @echo "#include <setjmp.h>" >> eet_amalgamation.c | ||
72 | @echo "#include <errno.h>" >> eet_amalgamation.c | ||
73 | @echo "#include <time.h>" >> eet_amalgamation.c | ||
74 | @echo "#include <fnmatch.h>" >> eet_amalgamation.c | ||
75 | @echo "#include <fcntl.h>" >> eet_amalgamation.c | ||
76 | |||
77 | @echo "#ifdef _WIN32" >> eet_amalgamation.c | ||
78 | @echo "# include <winsock2.h>" >> eet_amalgamation.c | ||
79 | @echo "#endif" >> eet_amalgamation.c | ||
80 | |||
81 | @echo "#ifndef _MSC_VER" >> eet_amalgamation.c | ||
82 | @echo "# include <unistd.h>" >> eet_amalgamation.c | ||
83 | @echo "#endif" >> eet_amalgamation.c | ||
84 | |||
85 | @echo "#ifdef HAVE_NETINET_IN_H" >> eet_amalgamation.c | ||
86 | @echo "# include <netinet/in.h>" >> eet_amalgamation.c | ||
87 | @echo "#endif" >> eet_amalgamation.c | ||
88 | |||
89 | @echo "#ifdef HAVE_GNUTLS" >> eet_amalgamation.c | ||
90 | @echo "# include <gnutls/gnutls.h>" >> eet_amalgamation.c | ||
91 | @echo "# include <gcrypt.h>" >> eet_amalgamation.c | ||
92 | @echo "#endif" >> eet_amalgamation.c | ||
93 | |||
94 | @echo "#ifdef HAVE_OPENSSL" >> eet_amalgamation.c | ||
95 | @echo "# include <openssl/err.h>" >> eet_amalgamation.c | ||
96 | @echo "# include <openssl/evp.h>" >> eet_amalgamation.c | ||
97 | @echo "# include <openssl/sha.h>" >> eet_amalgamation.c | ||
98 | @echo "#endif" >> eet_amalgamation.c | ||
99 | |||
100 | @echo "#ifdef HAVE_SIGNATURE" >> eet_amalgamation.c | ||
101 | @echo "# ifdef HAVE_GNUTLS" >> eet_amalgamation.c | ||
102 | @echo "# include <gnutls/gnutls.h>" >> eet_amalgamation.c | ||
103 | @echo "# include <gnutls/x509.h>" >> eet_amalgamation.c | ||
104 | @echo "# else" >> eet_amalgamation.c | ||
105 | @echo "# include <openssl/rsa.h>" >> eet_amalgamation.c | ||
106 | @echo "# include <openssl/objects.h>" >> eet_amalgamation.c | ||
107 | @echo "# include <openssl/err.h>" >> eet_amalgamation.c | ||
108 | @echo "# include <openssl/ssl.h>" >> eet_amalgamation.c | ||
109 | @echo "# include <openssl/dh.h>" >> eet_amalgamation.c | ||
110 | @echo "# include <openssl/dsa.h>" >> eet_amalgamation.c | ||
111 | @echo "# include <openssl/evp.h>" >> eet_amalgamation.c | ||
112 | @echo "# include <openssl/x509.h>" >> eet_amalgamation.c | ||
113 | @echo "# include <openssl/pem.h>" >> eet_amalgamation.c | ||
114 | @echo "# endif" >> eet_amalgamation.c | ||
115 | @echo "#endif" >> eet_amalgamation.c | ||
116 | |||
117 | @echo "#ifdef HAVE_CIPHER" >> eet_amalgamation.c | ||
118 | @echo "# ifdef HAVE_GNUTLS" >> eet_amalgamation.c | ||
119 | @echo "# include <gnutls/x509.h>" >> eet_amalgamation.c | ||
120 | @echo "# include <gcrypt.h>" >> eet_amalgamation.c | ||
121 | @echo "# else" >> eet_amalgamation.c | ||
122 | @echo "# include <openssl/evp.h>" >> eet_amalgamation.c | ||
123 | @echo "# include <openssl/hmac.h>" >> eet_amalgamation.c | ||
124 | @echo "# include <openssl/rand.h>" >> eet_amalgamation.c | ||
125 | @echo "# endif" >> eet_amalgamation.c | ||
126 | @echo "#endif" >> eet_amalgamation.c | ||
127 | |||
128 | @echo "#include <zlib.h>" >> eet_amalgamation.c | ||
129 | @echo "#include <jpeglib.h>" >> eet_amalgamation.c | ||
130 | |||
131 | @echo "#ifdef HAVE_EVIL" >> eet_amalgamation.c | ||
132 | @echo "# include <Evil.h>" >> eet_amalgamation.c | ||
133 | @echo "#endif" >> eet_amalgamation.c | ||
134 | |||
135 | @echo "#include <Eet.h>" >> eet_amalgamation.c | ||
136 | |||
137 | @echo "#include \"Eet_private.h\"" >> eet_amalgamation.c | ||
138 | @echo "#include \"Eet.h\"" >> eet_amalgamation.c | ||
139 | |||
140 | @for f in $(base_sources); do \ | ||
141 | if [ `echo $$f | sed -e 's/^...\(.\).*/\1/'` != '/' ]; then \ | ||
142 | file="$(srcdir)/$$f" ; \ | ||
143 | else \ | ||
144 | file="$$f" ; \ | ||
145 | fi ; \ | ||
146 | echo "/* file: $$file */" >> eet_amalgamation.c; \ | ||
147 | grep -v -e '^# *include \+.\(config\|\|Evil\|Eina\|stdio\|string\|math\|ctype\|limits\|sys/types\|sys/stat\|sys/mman\|setjmp\|errno\|time\|fnmatch\|fcntl\|winsock2\|unistd\|netinet/in\|gnutls/gnutls\|gcrypt\|gnutls/x509\|openssl/rsa\|openssl/objects\|openssl/err\|openssl/ssl\|openssl/dh\|openssl/dsa\|openssl/evp\|openssl/pem\|openssl/sha\|openssl/hmac\|openssl/x509\|openssl/rand\|zlib\|jpeglib\|Eet_private\|Eet\)[.]h.*' $$file >> eet_amalgamation.c; \ | ||
148 | done | ||
149 | @echo "eet_amalgamation.c generated" | ||
150 | |||
151 | else | ||
152 | libeet_la_SOURCES = $(base_sources) | ||
153 | endif | ||
154 | |||
155 | libeet_la_CFLAGS = @EET_CFLAGS@ @DEBUG_CFLAGS@ | ||
156 | libeet_la_LIBADD = @GNUTLS_LIBS@ @OPENSSL_LIBS@ @EFL_COVERAGE_LIBS@ @EET_LIBS@ @EINA_LIBS@ @EVIL_LIBS@ -lz -ljpeg -lm | ||
157 | libeet_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@ | ||
158 | |||
159 | EXTRA_DIST = Eet_private.h | ||
160 | |||
161 | clean-local: | ||
162 | @rm -rf *.gcno eet_amalgamation.c | ||
diff --git a/libraries/eet/src/lib/Makefile.in b/libraries/eet/src/lib/Makefile.in new file mode 100644 index 0000000..f80bcd8 --- /dev/null +++ b/libraries/eet/src/lib/Makefile.in | |||
@@ -0,0 +1,846 @@ | |||
1 | # Makefile.in generated by automake 1.11.1 from Makefile.am. | ||
2 | # @configure_input@ | ||
3 | |||
4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, | ||
5 | # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, | ||
6 | # Inc. | ||
7 | # This Makefile.in is free software; the Free Software Foundation | ||
8 | # gives unlimited permission to copy and/or distribute it, | ||
9 | # with or without modifications, as long as this notice is preserved. | ||
10 | |||
11 | # This program is distributed in the hope that it will be useful, | ||
12 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without | ||
13 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
14 | # PARTICULAR PURPOSE. | ||
15 | |||
16 | @SET_MAKE@ | ||
17 | |||
18 | |||
19 | VPATH = @srcdir@ | ||
20 | pkgdatadir = $(datadir)/@PACKAGE@ | ||
21 | pkgincludedir = $(includedir)/@PACKAGE@ | ||
22 | pkglibdir = $(libdir)/@PACKAGE@ | ||
23 | pkglibexecdir = $(libexecdir)/@PACKAGE@ | ||
24 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd | ||
25 | install_sh_DATA = $(install_sh) -c -m 644 | ||
26 | install_sh_PROGRAM = $(install_sh) -c | ||
27 | install_sh_SCRIPT = $(install_sh) -c | ||
28 | INSTALL_HEADER = $(INSTALL_DATA) | ||
29 | transform = $(program_transform_name) | ||
30 | NORMAL_INSTALL = : | ||
31 | PRE_INSTALL = : | ||
32 | POST_INSTALL = : | ||
33 | NORMAL_UNINSTALL = : | ||
34 | PRE_UNINSTALL = : | ||
35 | POST_UNINSTALL = : | ||
36 | build_triplet = @build@ | ||
37 | host_triplet = @host@ | ||
38 | subdir = src/lib | ||
39 | DIST_COMMON = $(includes_HEADERS) $(srcdir)/Makefile.am \ | ||
40 | $(srcdir)/Makefile.in | ||
41 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 | ||
42 | am__aclocal_m4_deps = $(top_srcdir)/m4/ac_attribute.m4 \ | ||
43 | $(top_srcdir)/m4/ac_path_generic.m4 \ | ||
44 | $(top_srcdir)/m4/efl_binary.m4 \ | ||
45 | $(top_srcdir)/m4/efl_compiler_flag.m4 \ | ||
46 | $(top_srcdir)/m4/efl_coverage.m4 \ | ||
47 | $(top_srcdir)/m4/efl_doxygen.m4 \ | ||
48 | $(top_srcdir)/m4/efl_fnmatch.m4 \ | ||
49 | $(top_srcdir)/m4/efl_path_max.m4 $(top_srcdir)/m4/efl_tests.m4 \ | ||
50 | $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ | ||
51 | $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ | ||
52 | $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac | ||
53 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ | ||
54 | $(ACLOCAL_M4) | ||
55 | mkinstalldirs = $(install_sh) -d | ||
56 | CONFIG_HEADER = $(top_builddir)/config.h | ||
57 | CONFIG_CLEAN_FILES = | ||
58 | CONFIG_CLEAN_VPATH_FILES = | ||
59 | am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | ||
60 | am__vpath_adj = case $$p in \ | ||
61 | $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ | ||
62 | *) f=$$p;; \ | ||
63 | esac; | ||
64 | am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; | ||
65 | am__install_max = 40 | ||
66 | am__nobase_strip_setup = \ | ||
67 | srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` | ||
68 | am__nobase_strip = \ | ||
69 | for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" | ||
70 | am__nobase_list = $(am__nobase_strip_setup); \ | ||
71 | for p in $$list; do echo "$$p $$p"; done | \ | ||
72 | sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ | ||
73 | $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ | ||
74 | if (++n[$$2] == $(am__install_max)) \ | ||
75 | { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ | ||
76 | END { for (dir in files) print dir, files[dir] }' | ||
77 | am__base_list = \ | ||
78 | sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ | ||
79 | sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | ||
80 | am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includesdir)" | ||
81 | LTLIBRARIES = $(lib_LTLIBRARIES) | ||
82 | libeet_la_DEPENDENCIES = | ||
83 | am__libeet_la_SOURCES_DIST = eet_lib.c eet_data.c eet_image.c \ | ||
84 | eet_cipher.c eet_dictionary.c eet_node.c eet_utils.c \ | ||
85 | eet_connection.c | ||
86 | am__objects_1 = libeet_la-eet_lib.lo libeet_la-eet_data.lo \ | ||
87 | libeet_la-eet_image.lo libeet_la-eet_cipher.lo \ | ||
88 | libeet_la-eet_dictionary.lo libeet_la-eet_node.lo \ | ||
89 | libeet_la-eet_utils.lo libeet_la-eet_connection.lo | ||
90 | @EET_AMALGAMATION_FALSE@am_libeet_la_OBJECTS = $(am__objects_1) | ||
91 | @EET_AMALGAMATION_TRUE@nodist_libeet_la_OBJECTS = \ | ||
92 | @EET_AMALGAMATION_TRUE@ libeet_la-eet_amalgamation.lo | ||
93 | libeet_la_OBJECTS = $(am_libeet_la_OBJECTS) \ | ||
94 | $(nodist_libeet_la_OBJECTS) | ||
95 | AM_V_lt = $(am__v_lt_$(V)) | ||
96 | am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) | ||
97 | am__v_lt_0 = --silent | ||
98 | libeet_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ | ||
99 | $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libeet_la_CFLAGS) \ | ||
100 | $(CFLAGS) $(libeet_la_LDFLAGS) $(LDFLAGS) -o $@ | ||
101 | DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) | ||
102 | depcomp = $(SHELL) $(top_srcdir)/depcomp | ||
103 | am__depfiles_maybe = depfiles | ||
104 | am__mv = mv -f | ||
105 | COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ | ||
106 | $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) | ||
107 | LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ | ||
108 | $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ | ||
109 | $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ | ||
110 | $(AM_CFLAGS) $(CFLAGS) | ||
111 | AM_V_CC = $(am__v_CC_$(V)) | ||
112 | am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) | ||
113 | am__v_CC_0 = @echo " CC " $@; | ||
114 | AM_V_at = $(am__v_at_$(V)) | ||
115 | am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) | ||
116 | am__v_at_0 = @ | ||
117 | CCLD = $(CC) | ||
118 | LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ | ||
119 | $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ | ||
120 | $(AM_LDFLAGS) $(LDFLAGS) -o $@ | ||
121 | AM_V_CCLD = $(am__v_CCLD_$(V)) | ||
122 | am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) | ||
123 | am__v_CCLD_0 = @echo " CCLD " $@; | ||
124 | AM_V_GEN = $(am__v_GEN_$(V)) | ||
125 | am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) | ||
126 | am__v_GEN_0 = @echo " GEN " $@; | ||
127 | SOURCES = $(libeet_la_SOURCES) $(nodist_libeet_la_SOURCES) | ||
128 | DIST_SOURCES = $(am__libeet_la_SOURCES_DIST) | ||
129 | HEADERS = $(includes_HEADERS) | ||
130 | ETAGS = etags | ||
131 | CTAGS = ctags | ||
132 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) | ||
133 | ACLOCAL = @ACLOCAL@ | ||
134 | ALLOCA = @ALLOCA@ | ||
135 | AMTAR = @AMTAR@ | ||
136 | AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ | ||
137 | AR = @AR@ | ||
138 | AS = @AS@ | ||
139 | AUTOCONF = @AUTOCONF@ | ||
140 | AUTOHEADER = @AUTOHEADER@ | ||
141 | AUTOMAKE = @AUTOMAKE@ | ||
142 | AWK = @AWK@ | ||
143 | CC = @CC@ | ||
144 | CCDEPMODE = @CCDEPMODE@ | ||
145 | CFLAGS = @CFLAGS@ | ||
146 | CHECK_CFLAGS = @CHECK_CFLAGS@ | ||
147 | CHECK_LIBS = @CHECK_LIBS@ | ||
148 | CPP = @CPP@ | ||
149 | CPPFLAGS = @CPPFLAGS@ | ||
150 | CYGPATH_W = @CYGPATH_W@ | ||
151 | DEBUG_CFLAGS = @DEBUG_CFLAGS@ | ||
152 | DEFS = @DEFS@ | ||
153 | DEPDIR = @DEPDIR@ | ||
154 | DLLTOOL = @DLLTOOL@ | ||
155 | DSYMUTIL = @DSYMUTIL@ | ||
156 | DUMPBIN = @DUMPBIN@ | ||
157 | ECHO_C = @ECHO_C@ | ||
158 | ECHO_N = @ECHO_N@ | ||
159 | ECHO_T = @ECHO_T@ | ||
160 | EET_CFLAGS = @EET_CFLAGS@ | ||
161 | EET_CPPFLAGS = @EET_CPPFLAGS@ | ||
162 | EET_LIBS = @EET_LIBS@ | ||
163 | EET_PRG = @EET_PRG@ | ||
164 | EFL_COVERAGE_CFLAGS = @EFL_COVERAGE_CFLAGS@ | ||
165 | EFL_COVERAGE_LIBS = @EFL_COVERAGE_LIBS@ | ||
166 | EFL_EET_BUILD = @EFL_EET_BUILD@ | ||
167 | EFL_FNMATCH_LIBS = @EFL_FNMATCH_LIBS@ | ||
168 | EGREP = @EGREP@ | ||
169 | EINA_CFLAGS = @EINA_CFLAGS@ | ||
170 | EINA_LIBS = @EINA_LIBS@ | ||
171 | EVIL_CFLAGS = @EVIL_CFLAGS@ | ||
172 | EVIL_LIBS = @EVIL_LIBS@ | ||
173 | EXEEXT = @EXEEXT@ | ||
174 | FGREP = @FGREP@ | ||
175 | GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ | ||
176 | GNUTLS_LIBS = @GNUTLS_LIBS@ | ||
177 | GREP = @GREP@ | ||
178 | INSTALL = @INSTALL@ | ||
179 | INSTALL_DATA = @INSTALL_DATA@ | ||
180 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ | ||
181 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ | ||
182 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ | ||
183 | LD = @LD@ | ||
184 | LDFLAGS = @LDFLAGS@ | ||
185 | LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ | ||
186 | LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ | ||
187 | LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ | ||
188 | LIBOBJS = @LIBOBJS@ | ||
189 | LIBS = @LIBS@ | ||
190 | LIBTOOL = @LIBTOOL@ | ||
191 | LIPO = @LIPO@ | ||
192 | LN_S = @LN_S@ | ||
193 | LTLIBOBJS = @LTLIBOBJS@ | ||
194 | MAKEINFO = @MAKEINFO@ | ||
195 | MKDIR_P = @MKDIR_P@ | ||
196 | NM = @NM@ | ||
197 | NMEDIT = @NMEDIT@ | ||
198 | OBJDUMP = @OBJDUMP@ | ||
199 | OBJEXT = @OBJEXT@ | ||
200 | OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ | ||
201 | OPENSSL_LIBS = @OPENSSL_LIBS@ | ||
202 | OTOOL = @OTOOL@ | ||
203 | OTOOL64 = @OTOOL64@ | ||
204 | PACKAGE = @PACKAGE@ | ||
205 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ | ||
206 | PACKAGE_NAME = @PACKAGE_NAME@ | ||
207 | PACKAGE_STRING = @PACKAGE_STRING@ | ||
208 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ | ||
209 | PACKAGE_URL = @PACKAGE_URL@ | ||
210 | PACKAGE_VERSION = @PACKAGE_VERSION@ | ||
211 | PATH_SEPARATOR = @PATH_SEPARATOR@ | ||
212 | PKG_CONFIG = @PKG_CONFIG@ | ||
213 | PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ | ||
214 | PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ | ||
215 | RANLIB = @RANLIB@ | ||
216 | SED = @SED@ | ||
217 | SET_MAKE = @SET_MAKE@ | ||
218 | SHELL = @SHELL@ | ||
219 | STRIP = @STRIP@ | ||
220 | VERSION = @VERSION@ | ||
221 | VMAJ = @VMAJ@ | ||
222 | abs_builddir = @abs_builddir@ | ||
223 | abs_srcdir = @abs_srcdir@ | ||
224 | abs_top_builddir = @abs_top_builddir@ | ||
225 | abs_top_srcdir = @abs_top_srcdir@ | ||
226 | ac_ct_CC = @ac_ct_CC@ | ||
227 | ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ | ||
228 | am__include = @am__include@ | ||
229 | am__leading_dot = @am__leading_dot@ | ||
230 | am__quote = @am__quote@ | ||
231 | am__tar = @am__tar@ | ||
232 | am__untar = @am__untar@ | ||
233 | bindir = @bindir@ | ||
234 | build = @build@ | ||
235 | build_alias = @build_alias@ | ||
236 | build_cpu = @build_cpu@ | ||
237 | build_os = @build_os@ | ||
238 | build_vendor = @build_vendor@ | ||
239 | builddir = @builddir@ | ||
240 | datadir = @datadir@ | ||
241 | datarootdir = @datarootdir@ | ||
242 | docdir = @docdir@ | ||
243 | dvidir = @dvidir@ | ||
244 | efl_doxygen = @efl_doxygen@ | ||
245 | efl_have_doxygen = @efl_have_doxygen@ | ||
246 | exec_prefix = @exec_prefix@ | ||
247 | have_lcov = @have_lcov@ | ||
248 | host = @host@ | ||
249 | host_alias = @host_alias@ | ||
250 | host_cpu = @host_cpu@ | ||
251 | host_os = @host_os@ | ||
252 | host_vendor = @host_vendor@ | ||
253 | htmldir = @htmldir@ | ||
254 | includedir = @includedir@ | ||
255 | infodir = @infodir@ | ||
256 | install_sh = @install_sh@ | ||
257 | libdir = @libdir@ | ||
258 | libexecdir = @libexecdir@ | ||
259 | localedir = @localedir@ | ||
260 | localstatedir = @localstatedir@ | ||
261 | lt_ECHO = @lt_ECHO@ | ||
262 | lt_enable_auto_import = @lt_enable_auto_import@ | ||
263 | mandir = @mandir@ | ||
264 | mkdir_p = @mkdir_p@ | ||
265 | oldincludedir = @oldincludedir@ | ||
266 | pdfdir = @pdfdir@ | ||
267 | pkgconfig_requires_private = @pkgconfig_requires_private@ | ||
268 | prefix = @prefix@ | ||
269 | program_transform_name = @program_transform_name@ | ||
270 | psdir = @psdir@ | ||
271 | release_info = @release_info@ | ||
272 | requirement_eet = @requirement_eet@ | ||
273 | sbindir = @sbindir@ | ||
274 | sharedstatedir = @sharedstatedir@ | ||
275 | srcdir = @srcdir@ | ||
276 | sysconfdir = @sysconfdir@ | ||
277 | target_alias = @target_alias@ | ||
278 | top_build_prefix = @top_build_prefix@ | ||
279 | top_builddir = @top_builddir@ | ||
280 | top_srcdir = @top_srcdir@ | ||
281 | version_info = @version_info@ | ||
282 | MAINTAINERCLEANFILES = Makefile.in | ||
283 | AM_CPPFLAGS = \ | ||
284 | -I. \ | ||
285 | -I$(top_srcdir)/src/lib \ | ||
286 | -I$(top_builddir)/src/lib \ | ||
287 | -DPACKAGE_BIN_DIR=\"$(bindir)\" \ | ||
288 | -DPACKAGE_LIB_DIR=\"$(libdir)\" \ | ||
289 | -DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ | ||
290 | @EVIL_CFLAGS@ \ | ||
291 | @EINA_CFLAGS@ \ | ||
292 | @EET_CPPFLAGS@ \ | ||
293 | @EFL_EET_BUILD@ \ | ||
294 | @EFL_COVERAGE_CFLAGS@ \ | ||
295 | @OPENSSL_CFLAGS@ \ | ||
296 | @GNUTLS_CFLAGS@ | ||
297 | |||
298 | includes_HEADERS = Eet.h | ||
299 | includesdir = $(includedir)/eet-@VMAJ@ | ||
300 | lib_LTLIBRARIES = libeet.la | ||
301 | base_sources = \ | ||
302 | eet_lib.c \ | ||
303 | eet_data.c \ | ||
304 | eet_image.c \ | ||
305 | eet_cipher.c \ | ||
306 | eet_dictionary.c \ | ||
307 | eet_node.c \ | ||
308 | eet_utils.c \ | ||
309 | eet_connection.c | ||
310 | |||
311 | @EET_AMALGAMATION_TRUE@nodist_libeet_la_SOURCES = eet_amalgamation.c | ||
312 | @EET_AMALGAMATION_FALSE@libeet_la_SOURCES = $(base_sources) | ||
313 | libeet_la_CFLAGS = @EET_CFLAGS@ @DEBUG_CFLAGS@ | ||
314 | libeet_la_LIBADD = @GNUTLS_LIBS@ @OPENSSL_LIBS@ @EFL_COVERAGE_LIBS@ @EET_LIBS@ @EINA_LIBS@ @EVIL_LIBS@ -lz -ljpeg -lm | ||
315 | libeet_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@ | ||
316 | EXTRA_DIST = Eet_private.h | ||
317 | all: all-am | ||
318 | |||
319 | .SUFFIXES: | ||
320 | .SUFFIXES: .c .lo .o .obj | ||
321 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) | ||
322 | @for dep in $?; do \ | ||
323 | case '$(am__configure_deps)' in \ | ||
324 | *$$dep*) \ | ||
325 | ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ | ||
326 | && { if test -f $@; then exit 0; else break; fi; }; \ | ||
327 | exit 1;; \ | ||
328 | esac; \ | ||
329 | done; \ | ||
330 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/lib/Makefile'; \ | ||
331 | $(am__cd) $(top_srcdir) && \ | ||
332 | $(AUTOMAKE) --gnu src/lib/Makefile | ||
333 | .PRECIOUS: Makefile | ||
334 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status | ||
335 | @case '$?' in \ | ||
336 | *config.status*) \ | ||
337 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ | ||
338 | *) \ | ||
339 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ | ||
340 | cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ | ||
341 | esac; | ||
342 | |||
343 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) | ||
344 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh | ||
345 | |||
346 | $(top_srcdir)/configure: $(am__configure_deps) | ||
347 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh | ||
348 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) | ||
349 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh | ||
350 | $(am__aclocal_m4_deps): | ||
351 | install-libLTLIBRARIES: $(lib_LTLIBRARIES) | ||
352 | @$(NORMAL_INSTALL) | ||
353 | test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" | ||
354 | @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ | ||
355 | list2=; for p in $$list; do \ | ||
356 | if test -f $$p; then \ | ||
357 | list2="$$list2 $$p"; \ | ||
358 | else :; fi; \ | ||
359 | done; \ | ||
360 | test -z "$$list2" || { \ | ||
361 | echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ | ||
362 | $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ | ||
363 | } | ||
364 | |||
365 | uninstall-libLTLIBRARIES: | ||
366 | @$(NORMAL_UNINSTALL) | ||
367 | @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ | ||
368 | for p in $$list; do \ | ||
369 | $(am__strip_dir) \ | ||
370 | echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ | ||
371 | $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ | ||
372 | done | ||
373 | |||
374 | clean-libLTLIBRARIES: | ||
375 | -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) | ||
376 | @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ | ||
377 | dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ | ||
378 | test "$$dir" != "$$p" || dir=.; \ | ||
379 | echo "rm -f \"$${dir}/so_locations\""; \ | ||
380 | rm -f "$${dir}/so_locations"; \ | ||
381 | done | ||
382 | libeet.la: $(libeet_la_OBJECTS) $(libeet_la_DEPENDENCIES) | ||
383 | $(AM_V_CCLD)$(libeet_la_LINK) -rpath $(libdir) $(libeet_la_OBJECTS) $(libeet_la_LIBADD) $(LIBS) | ||
384 | |||
385 | mostlyclean-compile: | ||
386 | -rm -f *.$(OBJEXT) | ||
387 | |||
388 | distclean-compile: | ||
389 | -rm -f *.tab.c | ||
390 | |||
391 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeet_la-eet_amalgamation.Plo@am__quote@ | ||
392 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeet_la-eet_cipher.Plo@am__quote@ | ||
393 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeet_la-eet_connection.Plo@am__quote@ | ||
394 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeet_la-eet_data.Plo@am__quote@ | ||
395 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeet_la-eet_dictionary.Plo@am__quote@ | ||
396 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeet_la-eet_image.Plo@am__quote@ | ||
397 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeet_la-eet_lib.Plo@am__quote@ | ||
398 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeet_la-eet_node.Plo@am__quote@ | ||
399 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libeet_la-eet_utils.Plo@am__quote@ | ||
400 | |||
401 | .c.o: | ||
402 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< | ||
403 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po | ||
404 | @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ | ||
405 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ | ||
406 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||
407 | @am__fastdepCC_FALSE@ $(COMPILE) -c $< | ||
408 | |||
409 | .c.obj: | ||
410 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` | ||
411 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po | ||
412 | @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ | ||
413 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ | ||
414 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||
415 | @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` | ||
416 | |||
417 | .c.lo: | ||
418 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< | ||
419 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo | ||
420 | @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ | ||
421 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ | ||
422 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||
423 | @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< | ||
424 | |||
425 | libeet_la-eet_lib.lo: eet_lib.c | ||
426 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -MT libeet_la-eet_lib.lo -MD -MP -MF $(DEPDIR)/libeet_la-eet_lib.Tpo -c -o libeet_la-eet_lib.lo `test -f 'eet_lib.c' || echo '$(srcdir)/'`eet_lib.c | ||
427 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeet_la-eet_lib.Tpo $(DEPDIR)/libeet_la-eet_lib.Plo | ||
428 | @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ | ||
429 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eet_lib.c' object='libeet_la-eet_lib.lo' libtool=yes @AMDEPBACKSLASH@ | ||
430 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||
431 | @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -c -o libeet_la-eet_lib.lo `test -f 'eet_lib.c' || echo '$(srcdir)/'`eet_lib.c | ||
432 | |||
433 | libeet_la-eet_data.lo: eet_data.c | ||
434 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -MT libeet_la-eet_data.lo -MD -MP -MF $(DEPDIR)/libeet_la-eet_data.Tpo -c -o libeet_la-eet_data.lo `test -f 'eet_data.c' || echo '$(srcdir)/'`eet_data.c | ||
435 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeet_la-eet_data.Tpo $(DEPDIR)/libeet_la-eet_data.Plo | ||
436 | @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ | ||
437 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eet_data.c' object='libeet_la-eet_data.lo' libtool=yes @AMDEPBACKSLASH@ | ||
438 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||
439 | @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -c -o libeet_la-eet_data.lo `test -f 'eet_data.c' || echo '$(srcdir)/'`eet_data.c | ||
440 | |||
441 | libeet_la-eet_image.lo: eet_image.c | ||
442 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -MT libeet_la-eet_image.lo -MD -MP -MF $(DEPDIR)/libeet_la-eet_image.Tpo -c -o libeet_la-eet_image.lo `test -f 'eet_image.c' || echo '$(srcdir)/'`eet_image.c | ||
443 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeet_la-eet_image.Tpo $(DEPDIR)/libeet_la-eet_image.Plo | ||
444 | @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ | ||
445 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eet_image.c' object='libeet_la-eet_image.lo' libtool=yes @AMDEPBACKSLASH@ | ||
446 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||
447 | @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -c -o libeet_la-eet_image.lo `test -f 'eet_image.c' || echo '$(srcdir)/'`eet_image.c | ||
448 | |||
449 | libeet_la-eet_cipher.lo: eet_cipher.c | ||
450 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -MT libeet_la-eet_cipher.lo -MD -MP -MF $(DEPDIR)/libeet_la-eet_cipher.Tpo -c -o libeet_la-eet_cipher.lo `test -f 'eet_cipher.c' || echo '$(srcdir)/'`eet_cipher.c | ||
451 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeet_la-eet_cipher.Tpo $(DEPDIR)/libeet_la-eet_cipher.Plo | ||
452 | @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ | ||
453 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eet_cipher.c' object='libeet_la-eet_cipher.lo' libtool=yes @AMDEPBACKSLASH@ | ||
454 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||
455 | @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -c -o libeet_la-eet_cipher.lo `test -f 'eet_cipher.c' || echo '$(srcdir)/'`eet_cipher.c | ||
456 | |||
457 | libeet_la-eet_dictionary.lo: eet_dictionary.c | ||
458 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -MT libeet_la-eet_dictionary.lo -MD -MP -MF $(DEPDIR)/libeet_la-eet_dictionary.Tpo -c -o libeet_la-eet_dictionary.lo `test -f 'eet_dictionary.c' || echo '$(srcdir)/'`eet_dictionary.c | ||
459 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeet_la-eet_dictionary.Tpo $(DEPDIR)/libeet_la-eet_dictionary.Plo | ||
460 | @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ | ||
461 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eet_dictionary.c' object='libeet_la-eet_dictionary.lo' libtool=yes @AMDEPBACKSLASH@ | ||
462 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||
463 | @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -c -o libeet_la-eet_dictionary.lo `test -f 'eet_dictionary.c' || echo '$(srcdir)/'`eet_dictionary.c | ||
464 | |||
465 | libeet_la-eet_node.lo: eet_node.c | ||
466 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -MT libeet_la-eet_node.lo -MD -MP -MF $(DEPDIR)/libeet_la-eet_node.Tpo -c -o libeet_la-eet_node.lo `test -f 'eet_node.c' || echo '$(srcdir)/'`eet_node.c | ||
467 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeet_la-eet_node.Tpo $(DEPDIR)/libeet_la-eet_node.Plo | ||
468 | @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ | ||
469 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eet_node.c' object='libeet_la-eet_node.lo' libtool=yes @AMDEPBACKSLASH@ | ||
470 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||
471 | @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -c -o libeet_la-eet_node.lo `test -f 'eet_node.c' || echo '$(srcdir)/'`eet_node.c | ||
472 | |||
473 | libeet_la-eet_utils.lo: eet_utils.c | ||
474 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -MT libeet_la-eet_utils.lo -MD -MP -MF $(DEPDIR)/libeet_la-eet_utils.Tpo -c -o libeet_la-eet_utils.lo `test -f 'eet_utils.c' || echo '$(srcdir)/'`eet_utils.c | ||
475 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeet_la-eet_utils.Tpo $(DEPDIR)/libeet_la-eet_utils.Plo | ||
476 | @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ | ||
477 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eet_utils.c' object='libeet_la-eet_utils.lo' libtool=yes @AMDEPBACKSLASH@ | ||
478 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||
479 | @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -c -o libeet_la-eet_utils.lo `test -f 'eet_utils.c' || echo '$(srcdir)/'`eet_utils.c | ||
480 | |||
481 | libeet_la-eet_connection.lo: eet_connection.c | ||
482 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -MT libeet_la-eet_connection.lo -MD -MP -MF $(DEPDIR)/libeet_la-eet_connection.Tpo -c -o libeet_la-eet_connection.lo `test -f 'eet_connection.c' || echo '$(srcdir)/'`eet_connection.c | ||
483 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeet_la-eet_connection.Tpo $(DEPDIR)/libeet_la-eet_connection.Plo | ||
484 | @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ | ||
485 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eet_connection.c' object='libeet_la-eet_connection.lo' libtool=yes @AMDEPBACKSLASH@ | ||
486 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||
487 | @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -c -o libeet_la-eet_connection.lo `test -f 'eet_connection.c' || echo '$(srcdir)/'`eet_connection.c | ||
488 | |||
489 | libeet_la-eet_amalgamation.lo: eet_amalgamation.c | ||
490 | @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -MT libeet_la-eet_amalgamation.lo -MD -MP -MF $(DEPDIR)/libeet_la-eet_amalgamation.Tpo -c -o libeet_la-eet_amalgamation.lo `test -f 'eet_amalgamation.c' || echo '$(srcdir)/'`eet_amalgamation.c | ||
491 | @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libeet_la-eet_amalgamation.Tpo $(DEPDIR)/libeet_la-eet_amalgamation.Plo | ||
492 | @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ | ||
493 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eet_amalgamation.c' object='libeet_la-eet_amalgamation.lo' libtool=yes @AMDEPBACKSLASH@ | ||
494 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||
495 | @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libeet_la_CFLAGS) $(CFLAGS) -c -o libeet_la-eet_amalgamation.lo `test -f 'eet_amalgamation.c' || echo '$(srcdir)/'`eet_amalgamation.c | ||
496 | |||
497 | mostlyclean-libtool: | ||
498 | -rm -f *.lo | ||
499 | |||
500 | clean-libtool: | ||
501 | -rm -rf .libs _libs | ||
502 | install-includesHEADERS: $(includes_HEADERS) | ||
503 | @$(NORMAL_INSTALL) | ||
504 | test -z "$(includesdir)" || $(MKDIR_P) "$(DESTDIR)$(includesdir)" | ||
505 | @list='$(includes_HEADERS)'; test -n "$(includesdir)" || list=; \ | ||
506 | for p in $$list; do \ | ||
507 | if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ | ||
508 | echo "$$d$$p"; \ | ||
509 | done | $(am__base_list) | \ | ||
510 | while read files; do \ | ||
511 | echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includesdir)'"; \ | ||
512 | $(INSTALL_HEADER) $$files "$(DESTDIR)$(includesdir)" || exit $$?; \ | ||
513 | done | ||
514 | |||
515 | uninstall-includesHEADERS: | ||
516 | @$(NORMAL_UNINSTALL) | ||
517 | @list='$(includes_HEADERS)'; test -n "$(includesdir)" || list=; \ | ||
518 | files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ | ||
519 | test -n "$$files" || exit 0; \ | ||
520 | echo " ( cd '$(DESTDIR)$(includesdir)' && rm -f" $$files ")"; \ | ||
521 | cd "$(DESTDIR)$(includesdir)" && rm -f $$files | ||
522 | |||
523 | ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) | ||
524 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ | ||
525 | unique=`for i in $$list; do \ | ||
526 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ | ||
527 | done | \ | ||
528 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ | ||
529 | END { if (nonempty) { for (i in files) print i; }; }'`; \ | ||
530 | mkid -fID $$unique | ||
531 | tags: TAGS | ||
532 | |||
533 | TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ | ||
534 | $(TAGS_FILES) $(LISP) | ||
535 | set x; \ | ||
536 | here=`pwd`; \ | ||
537 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ | ||
538 | unique=`for i in $$list; do \ | ||
539 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ | ||
540 | done | \ | ||
541 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ | ||
542 | END { if (nonempty) { for (i in files) print i; }; }'`; \ | ||
543 | shift; \ | ||
544 | if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ | ||
545 | test -n "$$unique" || unique=$$empty_fix; \ | ||
546 | if test $$# -gt 0; then \ | ||
547 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ | ||
548 | "$$@" $$unique; \ | ||
549 | else \ | ||
550 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ | ||
551 | $$unique; \ | ||
552 | fi; \ | ||
553 | fi | ||
554 | ctags: CTAGS | ||
555 | CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ | ||
556 | $(TAGS_FILES) $(LISP) | ||
557 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ | ||
558 | unique=`for i in $$list; do \ | ||
559 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ | ||
560 | done | \ | ||
561 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ | ||
562 | END { if (nonempty) { for (i in files) print i; }; }'`; \ | ||
563 | test -z "$(CTAGS_ARGS)$$unique" \ | ||
564 | || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ | ||
565 | $$unique | ||
566 | |||
567 | GTAGS: | ||
568 | here=`$(am__cd) $(top_builddir) && pwd` \ | ||
569 | && $(am__cd) $(top_srcdir) \ | ||
570 | && gtags -i $(GTAGS_ARGS) "$$here" | ||
571 | |||
572 | distclean-tags: | ||
573 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags | ||
574 | |||
575 | distdir: $(DISTFILES) | ||
576 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ | ||
577 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ | ||
578 | list='$(DISTFILES)'; \ | ||
579 | dist_files=`for file in $$list; do echo $$file; done | \ | ||
580 | sed -e "s|^$$srcdirstrip/||;t" \ | ||
581 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ | ||
582 | case $$dist_files in \ | ||
583 | */*) $(MKDIR_P) `echo "$$dist_files" | \ | ||
584 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ | ||
585 | sort -u` ;; \ | ||
586 | esac; \ | ||
587 | for file in $$dist_files; do \ | ||
588 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ | ||
589 | if test -d $$d/$$file; then \ | ||
590 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ | ||
591 | if test -d "$(distdir)/$$file"; then \ | ||
592 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ | ||
593 | fi; \ | ||
594 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ | ||
595 | cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ | ||
596 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ | ||
597 | fi; \ | ||
598 | cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ | ||
599 | else \ | ||
600 | test -f "$(distdir)/$$file" \ | ||
601 | || cp -p $$d/$$file "$(distdir)/$$file" \ | ||
602 | || exit 1; \ | ||
603 | fi; \ | ||
604 | done | ||
605 | check-am: all-am | ||
606 | check: check-am | ||
607 | all-am: Makefile $(LTLIBRARIES) $(HEADERS) | ||
608 | installdirs: | ||
609 | for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includesdir)"; do \ | ||
610 | test -z "$$dir" || $(MKDIR_P) "$$dir"; \ | ||
611 | done | ||
612 | install: install-am | ||
613 | install-exec: install-exec-am | ||
614 | install-data: install-data-am | ||
615 | uninstall: uninstall-am | ||
616 | |||
617 | install-am: all-am | ||
618 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am | ||
619 | |||
620 | installcheck: installcheck-am | ||
621 | install-strip: | ||
622 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ | ||
623 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ | ||
624 | `test -z '$(STRIP)' || \ | ||
625 | echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install | ||
626 | mostlyclean-generic: | ||
627 | |||
628 | clean-generic: | ||
629 | |||
630 | distclean-generic: | ||
631 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) | ||
632 | -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) | ||
633 | |||
634 | maintainer-clean-generic: | ||
635 | @echo "This command is intended for maintainers to use" | ||
636 | @echo "it deletes files that may require special tools to rebuild." | ||
637 | -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) | ||
638 | clean: clean-am | ||
639 | |||
640 | clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ | ||
641 | mostlyclean-am | ||
642 | |||
643 | distclean: distclean-am | ||
644 | -rm -rf ./$(DEPDIR) | ||
645 | -rm -f Makefile | ||
646 | distclean-am: clean-am distclean-compile distclean-generic \ | ||
647 | distclean-tags | ||
648 | |||
649 | dvi: dvi-am | ||
650 | |||
651 | dvi-am: | ||
652 | |||
653 | html: html-am | ||
654 | |||
655 | html-am: | ||
656 | |||
657 | info: info-am | ||
658 | |||
659 | info-am: | ||
660 | |||
661 | install-data-am: install-includesHEADERS | ||
662 | |||
663 | install-dvi: install-dvi-am | ||
664 | |||
665 | install-dvi-am: | ||
666 | |||
667 | install-exec-am: install-libLTLIBRARIES | ||
668 | |||
669 | install-html: install-html-am | ||
670 | |||
671 | install-html-am: | ||
672 | |||
673 | install-info: install-info-am | ||
674 | |||
675 | install-info-am: | ||
676 | |||
677 | install-man: | ||
678 | |||
679 | install-pdf: install-pdf-am | ||
680 | |||
681 | install-pdf-am: | ||
682 | |||
683 | install-ps: install-ps-am | ||
684 | |||
685 | install-ps-am: | ||
686 | |||
687 | installcheck-am: | ||
688 | |||
689 | maintainer-clean: maintainer-clean-am | ||
690 | -rm -rf ./$(DEPDIR) | ||
691 | -rm -f Makefile | ||
692 | maintainer-clean-am: distclean-am maintainer-clean-generic | ||
693 | |||
694 | mostlyclean: mostlyclean-am | ||
695 | |||
696 | mostlyclean-am: mostlyclean-compile mostlyclean-generic \ | ||
697 | mostlyclean-libtool | ||
698 | |||
699 | pdf: pdf-am | ||
700 | |||
701 | pdf-am: | ||
702 | |||
703 | ps: ps-am | ||
704 | |||
705 | ps-am: | ||
706 | |||
707 | uninstall-am: uninstall-includesHEADERS uninstall-libLTLIBRARIES | ||
708 | |||
709 | .MAKE: install-am install-strip | ||
710 | |||
711 | .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ | ||
712 | clean-libLTLIBRARIES clean-libtool clean-local ctags distclean \ | ||
713 | distclean-compile distclean-generic distclean-libtool \ | ||
714 | distclean-tags distdir dvi dvi-am html html-am info info-am \ | ||
715 | install install-am install-data install-data-am install-dvi \ | ||
716 | install-dvi-am install-exec install-exec-am install-html \ | ||
717 | install-html-am install-includesHEADERS install-info \ | ||
718 | install-info-am install-libLTLIBRARIES install-man install-pdf \ | ||
719 | install-pdf-am install-ps install-ps-am install-strip \ | ||
720 | installcheck installcheck-am installdirs maintainer-clean \ | ||
721 | maintainer-clean-generic mostlyclean mostlyclean-compile \ | ||
722 | mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ | ||
723 | tags uninstall uninstall-am uninstall-includesHEADERS \ | ||
724 | uninstall-libLTLIBRARIES | ||
725 | |||
726 | |||
727 | @EET_AMALGAMATION_TRUE@eet_amalgamation.c: $(base_sources) Makefile | ||
728 | @EET_AMALGAMATION_TRUE@ -rm -f eet_amalgamation.c | ||
729 | |||
730 | @EET_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_CONFIG_H" >> eet_amalgamation.c | ||
731 | @EET_AMALGAMATION_TRUE@ @echo "# include \"config.h\"" >> eet_amalgamation.c | ||
732 | @EET_AMALGAMATION_TRUE@ @echo "#endif" >> eet_amalgamation.c | ||
733 | |||
734 | @EET_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_ALLOCA_H" >> eet_amalgamation.c | ||
735 | @EET_AMALGAMATION_TRUE@ @echo "# include <alloca.h>" >> eet_amalgamation.c | ||
736 | @EET_AMALGAMATION_TRUE@ @echo "#elif defined __GNUC__" >> eet_amalgamation.c | ||
737 | @EET_AMALGAMATION_TRUE@ @echo "# define alloca __builtin_alloca" >> eet_amalgamation.c | ||
738 | @EET_AMALGAMATION_TRUE@ @echo "#elif defined _AIX" >> eet_amalgamation.c | ||
739 | @EET_AMALGAMATION_TRUE@ @echo "# define alloca __alloca" >> eet_amalgamation.c | ||
740 | @EET_AMALGAMATION_TRUE@ @echo "#elif defined _MSC_VER" >> eet_amalgamation.c | ||
741 | @EET_AMALGAMATION_TRUE@ @echo "# include <malloc.h>" >> eet_amalgamation.c | ||
742 | @EET_AMALGAMATION_TRUE@ @echo "# define alloca _alloca" >> eet_amalgamation.c | ||
743 | @EET_AMALGAMATION_TRUE@ @echo "#else" >> eet_amalgamation.c | ||
744 | @EET_AMALGAMATION_TRUE@ @echo "# include <stddef.h>" >> eet_amalgamation.c | ||
745 | @EET_AMALGAMATION_TRUE@ @echo "# ifdef __cplusplus" >> eet_amalgamation.c | ||
746 | @EET_AMALGAMATION_TRUE@ @echo "#extern \"C\"" >> eet_amalgamation.c | ||
747 | @EET_AMALGAMATION_TRUE@ @echo "# endif" >> eet_amalgamation.c | ||
748 | @EET_AMALGAMATION_TRUE@ @echo "#void *alloca (size_t);" >> eet_amalgamation.c | ||
749 | @EET_AMALGAMATION_TRUE@ @echo "#endif" >> eet_amalgamation.c | ||
750 | |||
751 | @EET_AMALGAMATION_TRUE@ @echo "#include <stdio.h>" >> eet_amalgamation.c | ||
752 | @EET_AMALGAMATION_TRUE@ @echo "#include <string.h>" >> eet_amalgamation.c | ||
753 | @EET_AMALGAMATION_TRUE@ @echo "#include <math.h>" >> eet_amalgamation.c | ||
754 | @EET_AMALGAMATION_TRUE@ @echo "#include <ctype.h>" >> eet_amalgamation.c | ||
755 | @EET_AMALGAMATION_TRUE@ @echo "#include <limits.h>" >> eet_amalgamation.c | ||
756 | @EET_AMALGAMATION_TRUE@ @echo "#include <sys/types.h>" >> eet_amalgamation.c | ||
757 | @EET_AMALGAMATION_TRUE@ @echo "#include <sys/stat.h>" >> eet_amalgamation.c | ||
758 | @EET_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_SIGNATURE" >> eet_amalgamation.c | ||
759 | @EET_AMALGAMATION_TRUE@ @echo "# include <sys/mman.h>" >> eet_amalgamation.c | ||
760 | @EET_AMALGAMATION_TRUE@ @echo "#endif" >> eet_amalgamation.c | ||
761 | @EET_AMALGAMATION_TRUE@ @echo "#include <setjmp.h>" >> eet_amalgamation.c | ||
762 | @EET_AMALGAMATION_TRUE@ @echo "#include <errno.h>" >> eet_amalgamation.c | ||
763 | @EET_AMALGAMATION_TRUE@ @echo "#include <time.h>" >> eet_amalgamation.c | ||
764 | @EET_AMALGAMATION_TRUE@ @echo "#include <fnmatch.h>" >> eet_amalgamation.c | ||
765 | @EET_AMALGAMATION_TRUE@ @echo "#include <fcntl.h>" >> eet_amalgamation.c | ||
766 | |||
767 | @EET_AMALGAMATION_TRUE@ @echo "#ifdef _WIN32" >> eet_amalgamation.c | ||
768 | @EET_AMALGAMATION_TRUE@ @echo "# include <winsock2.h>" >> eet_amalgamation.c | ||
769 | @EET_AMALGAMATION_TRUE@ @echo "#endif" >> eet_amalgamation.c | ||
770 | |||
771 | @EET_AMALGAMATION_TRUE@ @echo "#ifndef _MSC_VER" >> eet_amalgamation.c | ||
772 | @EET_AMALGAMATION_TRUE@ @echo "# include <unistd.h>" >> eet_amalgamation.c | ||
773 | @EET_AMALGAMATION_TRUE@ @echo "#endif" >> eet_amalgamation.c | ||
774 | |||
775 | @EET_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_NETINET_IN_H" >> eet_amalgamation.c | ||
776 | @EET_AMALGAMATION_TRUE@ @echo "# include <netinet/in.h>" >> eet_amalgamation.c | ||
777 | @EET_AMALGAMATION_TRUE@ @echo "#endif" >> eet_amalgamation.c | ||
778 | |||
779 | @EET_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_GNUTLS" >> eet_amalgamation.c | ||
780 | @EET_AMALGAMATION_TRUE@ @echo "# include <gnutls/gnutls.h>" >> eet_amalgamation.c | ||
781 | @EET_AMALGAMATION_TRUE@ @echo "# include <gcrypt.h>" >> eet_amalgamation.c | ||
782 | @EET_AMALGAMATION_TRUE@ @echo "#endif" >> eet_amalgamation.c | ||
783 | |||
784 | @EET_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_OPENSSL" >> eet_amalgamation.c | ||
785 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/err.h>" >> eet_amalgamation.c | ||
786 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/evp.h>" >> eet_amalgamation.c | ||
787 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/sha.h>" >> eet_amalgamation.c | ||
788 | @EET_AMALGAMATION_TRUE@ @echo "#endif" >> eet_amalgamation.c | ||
789 | |||
790 | @EET_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_SIGNATURE" >> eet_amalgamation.c | ||
791 | @EET_AMALGAMATION_TRUE@ @echo "# ifdef HAVE_GNUTLS" >> eet_amalgamation.c | ||
792 | @EET_AMALGAMATION_TRUE@ @echo "# include <gnutls/gnutls.h>" >> eet_amalgamation.c | ||
793 | @EET_AMALGAMATION_TRUE@ @echo "# include <gnutls/x509.h>" >> eet_amalgamation.c | ||
794 | @EET_AMALGAMATION_TRUE@ @echo "# else" >> eet_amalgamation.c | ||
795 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/rsa.h>" >> eet_amalgamation.c | ||
796 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/objects.h>" >> eet_amalgamation.c | ||
797 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/err.h>" >> eet_amalgamation.c | ||
798 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/ssl.h>" >> eet_amalgamation.c | ||
799 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/dh.h>" >> eet_amalgamation.c | ||
800 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/dsa.h>" >> eet_amalgamation.c | ||
801 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/evp.h>" >> eet_amalgamation.c | ||
802 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/x509.h>" >> eet_amalgamation.c | ||
803 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/pem.h>" >> eet_amalgamation.c | ||
804 | @EET_AMALGAMATION_TRUE@ @echo "# endif" >> eet_amalgamation.c | ||
805 | @EET_AMALGAMATION_TRUE@ @echo "#endif" >> eet_amalgamation.c | ||
806 | |||
807 | @EET_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_CIPHER" >> eet_amalgamation.c | ||
808 | @EET_AMALGAMATION_TRUE@ @echo "# ifdef HAVE_GNUTLS" >> eet_amalgamation.c | ||
809 | @EET_AMALGAMATION_TRUE@ @echo "# include <gnutls/x509.h>" >> eet_amalgamation.c | ||
810 | @EET_AMALGAMATION_TRUE@ @echo "# include <gcrypt.h>" >> eet_amalgamation.c | ||
811 | @EET_AMALGAMATION_TRUE@ @echo "# else" >> eet_amalgamation.c | ||
812 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/evp.h>" >> eet_amalgamation.c | ||
813 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/hmac.h>" >> eet_amalgamation.c | ||
814 | @EET_AMALGAMATION_TRUE@ @echo "# include <openssl/rand.h>" >> eet_amalgamation.c | ||
815 | @EET_AMALGAMATION_TRUE@ @echo "# endif" >> eet_amalgamation.c | ||
816 | @EET_AMALGAMATION_TRUE@ @echo "#endif" >> eet_amalgamation.c | ||
817 | |||
818 | @EET_AMALGAMATION_TRUE@ @echo "#include <zlib.h>" >> eet_amalgamation.c | ||
819 | @EET_AMALGAMATION_TRUE@ @echo "#include <jpeglib.h>" >> eet_amalgamation.c | ||
820 | |||
821 | @EET_AMALGAMATION_TRUE@ @echo "#ifdef HAVE_EVIL" >> eet_amalgamation.c | ||
822 | @EET_AMALGAMATION_TRUE@ @echo "# include <Evil.h>" >> eet_amalgamation.c | ||
823 | @EET_AMALGAMATION_TRUE@ @echo "#endif" >> eet_amalgamation.c | ||
824 | |||
825 | @EET_AMALGAMATION_TRUE@ @echo "#include <Eet.h>" >> eet_amalgamation.c | ||
826 | |||
827 | @EET_AMALGAMATION_TRUE@ @echo "#include \"Eet_private.h\"" >> eet_amalgamation.c | ||
828 | @EET_AMALGAMATION_TRUE@ @echo "#include \"Eet.h\"" >> eet_amalgamation.c | ||
829 | |||
830 | @EET_AMALGAMATION_TRUE@ @for f in $(base_sources); do \ | ||
831 | @EET_AMALGAMATION_TRUE@ if [ `echo $$f | sed -e 's/^...\(.\).*/\1/'` != '/' ]; then \ | ||
832 | @EET_AMALGAMATION_TRUE@ file="$(srcdir)/$$f" ; \ | ||
833 | @EET_AMALGAMATION_TRUE@ else \ | ||
834 | @EET_AMALGAMATION_TRUE@ file="$$f" ; \ | ||
835 | @EET_AMALGAMATION_TRUE@ fi ; \ | ||
836 | @EET_AMALGAMATION_TRUE@ echo "/* file: $$file */" >> eet_amalgamation.c; \ | ||
837 | @EET_AMALGAMATION_TRUE@ grep -v -e '^# *include \+.\(config\|\|Evil\|Eina\|stdio\|string\|math\|ctype\|limits\|sys/types\|sys/stat\|sys/mman\|setjmp\|errno\|time\|fnmatch\|fcntl\|winsock2\|unistd\|netinet/in\|gnutls/gnutls\|gcrypt\|gnutls/x509\|openssl/rsa\|openssl/objects\|openssl/err\|openssl/ssl\|openssl/dh\|openssl/dsa\|openssl/evp\|openssl/pem\|openssl/sha\|openssl/hmac\|openssl/x509\|openssl/rand\|zlib\|jpeglib\|Eet_private\|Eet\)[.]h.*' $$file >> eet_amalgamation.c; \ | ||
838 | @EET_AMALGAMATION_TRUE@ done | ||
839 | @EET_AMALGAMATION_TRUE@ @echo "eet_amalgamation.c generated" | ||
840 | |||
841 | clean-local: | ||
842 | @rm -rf *.gcno eet_amalgamation.c | ||
843 | |||
844 | # Tell versions [3.59,3.63) of GNU make to not export all variables. | ||
845 | # Otherwise a system limit (for SysV at least) may be exceeded. | ||
846 | .NOEXPORT: | ||
diff --git a/libraries/eet/src/lib/eet_cipher.c b/libraries/eet/src/lib/eet_cipher.c new file mode 100644 index 0000000..89ee65d --- /dev/null +++ b/libraries/eet/src/lib/eet_cipher.c | |||
@@ -0,0 +1,1342 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif /* ifdef HAVE_CONFIG_H */ | ||
4 | |||
5 | #ifdef HAVE_ALLOCA_H | ||
6 | # include <alloca.h> | ||
7 | #elif defined __GNUC__ | ||
8 | # define alloca __builtin_alloca | ||
9 | #elif defined _AIX | ||
10 | # define alloca __alloca | ||
11 | #elif defined _MSC_VER | ||
12 | # include <malloc.h> | ||
13 | # define alloca _alloca | ||
14 | #else /* ifdef HAVE_ALLOCA_H */ | ||
15 | # include <stddef.h> | ||
16 | # ifdef __cplusplus | ||
17 | extern "C" | ||
18 | # endif /* ifdef __cplusplus */ | ||
19 | void *alloca(size_t); | ||
20 | #endif /* ifdef HAVE_ALLOCA_H */ | ||
21 | |||
22 | #include <stdio.h> | ||
23 | #include <string.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <sys/stat.h> | ||
26 | |||
27 | #ifdef HAVE_UNISTD_H | ||
28 | # include <unistd.h> | ||
29 | #endif /* ifdef HAVE_UNISTD_H */ | ||
30 | |||
31 | #ifdef HAVE_NETINET_IN_H | ||
32 | # include <netinet/in.h> | ||
33 | #endif /* ifdef HAVE_NETINET_IN_H */ | ||
34 | |||
35 | #ifdef HAVE_SIGNATURE | ||
36 | # include <sys/mman.h> | ||
37 | # ifdef HAVE_GNUTLS | ||
38 | # include <gnutls/gnutls.h> | ||
39 | # include <gnutls/x509.h> | ||
40 | # else /* ifdef HAVE_GNUTLS */ | ||
41 | # include <openssl/rsa.h> | ||
42 | # include <openssl/objects.h> | ||
43 | # include <openssl/err.h> | ||
44 | # include <openssl/ssl.h> | ||
45 | # include <openssl/dh.h> | ||
46 | # include <openssl/dsa.h> | ||
47 | # include <openssl/evp.h> | ||
48 | # include <openssl/x509.h> | ||
49 | # include <openssl/pem.h> | ||
50 | # endif /* ifdef HAVE_GNUTLS */ | ||
51 | #endif /* ifdef HAVE_SIGNATURE */ | ||
52 | |||
53 | #ifdef HAVE_OPENSSL | ||
54 | # include <openssl/sha.h> | ||
55 | #endif /* ifdef HAVE_OPENSSL */ | ||
56 | |||
57 | #ifdef HAVE_CIPHER | ||
58 | # ifdef HAVE_GNUTLS | ||
59 | # include <gnutls/x509.h> | ||
60 | # include <gcrypt.h> | ||
61 | # else /* ifdef HAVE_GNUTLS */ | ||
62 | # include <openssl/evp.h> | ||
63 | # include <openssl/hmac.h> | ||
64 | # include <openssl/rand.h> | ||
65 | # endif /* ifdef HAVE_GNUTLS */ | ||
66 | #endif /* ifdef HAVE_CIPHER */ | ||
67 | |||
68 | #include "Eet.h" | ||
69 | #include "Eet_private.h" | ||
70 | |||
71 | #define EET_MAGIC_SIGN 0x1ee74271 | ||
72 | |||
73 | #ifdef HAVE_GNUTLS | ||
74 | # define MAX_KEY_LEN 32 | ||
75 | # define MAX_IV_LEN 16 | ||
76 | #else /* ifdef HAVE_GNUTLS */ | ||
77 | # define MAX_KEY_LEN EVP_MAX_KEY_LENGTH | ||
78 | # define MAX_IV_LEN EVP_MAX_IV_LENGTH | ||
79 | #endif /* ifdef HAVE_GNUTLS */ | ||
80 | |||
81 | #ifdef HAVE_CIPHER | ||
82 | # ifdef HAVE_GNUTLS | ||
83 | static Eet_Error | ||
84 | eet_hmac_sha1(const void *key, | ||
85 | size_t key_len, | ||
86 | const void *data, | ||
87 | size_t data_len, | ||
88 | unsigned char *res); | ||
89 | # endif /* ifdef HAVE_GNUTLS */ | ||
90 | static Eet_Error | ||
91 | eet_pbkdf2_sha1(const char *key, | ||
92 | int key_len, | ||
93 | const unsigned char *salt, | ||
94 | unsigned int salt_len, | ||
95 | int iter, | ||
96 | unsigned char *res, | ||
97 | int res_len); | ||
98 | #endif /* ifdef HAVE_CIPHER */ | ||
99 | |||
100 | struct _Eet_Key | ||
101 | { | ||
102 | int references; | ||
103 | #ifdef HAVE_SIGNATURE | ||
104 | # ifdef HAVE_GNUTLS | ||
105 | gnutls_x509_crt_t certificate; | ||
106 | gnutls_x509_privkey_t private_key; | ||
107 | # else /* ifdef HAVE_GNUTLS */ | ||
108 | X509 *certificate; | ||
109 | EVP_PKEY *private_key; | ||
110 | # endif /* ifdef HAVE_GNUTLS */ | ||
111 | #endif /* ifdef HAVE_SIGNATURE */ | ||
112 | }; | ||
113 | |||
114 | EAPI Eet_Key * | ||
115 | eet_identity_open(const char *certificate_file, | ||
116 | const char *private_key_file, | ||
117 | Eet_Key_Password_Callback cb) | ||
118 | { | ||
119 | #ifdef HAVE_SIGNATURE | ||
120 | /* Signature declarations */ | ||
121 | Eet_Key *key = NULL; | ||
122 | # ifdef HAVE_GNUTLS | ||
123 | /* Gnutls private declarations */ | ||
124 | Eina_File *f = NULL; | ||
125 | void *data = NULL; | ||
126 | gnutls_datum_t load_file = { NULL, 0 }; | ||
127 | char pass[1024]; | ||
128 | |||
129 | /* Init */ | ||
130 | if (!(key = malloc(sizeof(Eet_Key)))) | ||
131 | goto on_error; | ||
132 | |||
133 | key->references = 1; | ||
134 | |||
135 | if (gnutls_x509_crt_init(&(key->certificate))) | ||
136 | goto on_error; | ||
137 | |||
138 | if (gnutls_x509_privkey_init(&(key->private_key))) | ||
139 | goto on_error; | ||
140 | |||
141 | /* Mmap certificate_file */ | ||
142 | f = eina_file_open(certificate_file, 0); | ||
143 | if (!f) | ||
144 | goto on_error; | ||
145 | |||
146 | /* let's make mmap safe and just get 0 pages for IO erro */ | ||
147 | eina_mmap_safety_enabled_set(EINA_TRUE); | ||
148 | |||
149 | data = eina_file_map_all(f, EINA_FILE_SEQUENTIAL); | ||
150 | if (!data) goto on_error; | ||
151 | |||
152 | /* Import the certificate in Eet_Key structure */ | ||
153 | load_file.data = data; | ||
154 | load_file.size = eina_file_size_get(f); | ||
155 | if (gnutls_x509_crt_import(key->certificate, &load_file, | ||
156 | GNUTLS_X509_FMT_PEM) < 0) | ||
157 | goto on_error; | ||
158 | |||
159 | eina_file_map_free(f, data); | ||
160 | |||
161 | /* Reset values */ | ||
162 | eina_file_close(f); | ||
163 | f = NULL; | ||
164 | data = NULL; | ||
165 | load_file.data = NULL; | ||
166 | load_file.size = 0; | ||
167 | |||
168 | /* Mmap private_key_file */ | ||
169 | f = eina_file_open(private_key_file, 0); | ||
170 | if (!f) | ||
171 | goto on_error; | ||
172 | |||
173 | /* let's make mmap safe and just get 0 pages for IO erro */ | ||
174 | eina_mmap_safety_enabled_set(EINA_TRUE); | ||
175 | |||
176 | data = eina_file_map_all(f, EINA_FILE_SEQUENTIAL); | ||
177 | if (!data) | ||
178 | goto on_error; | ||
179 | |||
180 | /* Import the private key in Eet_Key structure */ | ||
181 | load_file.data = data; | ||
182 | load_file.size = eina_file_size_get(f); | ||
183 | /* Try to directly import the PEM encoded private key */ | ||
184 | if (gnutls_x509_privkey_import(key->private_key, &load_file, | ||
185 | GNUTLS_X509_FMT_PEM) < 0) | ||
186 | { | ||
187 | /* Else ask for the private key pass */ | ||
188 | if (cb && cb(pass, 1024, 0, NULL)) | ||
189 | { | ||
190 | /* If pass then try to decode the pkcs 8 private key */ | ||
191 | if (gnutls_x509_privkey_import_pkcs8(key->private_key, &load_file, | ||
192 | GNUTLS_X509_FMT_PEM, pass, 0)) | ||
193 | goto on_error; | ||
194 | } | ||
195 | else | ||
196 | /* Else try to import the pkcs 8 private key without pass */ | ||
197 | if (gnutls_x509_privkey_import_pkcs8(key->private_key, &load_file, | ||
198 | GNUTLS_X509_FMT_PEM, NULL, 1)) | ||
199 | goto on_error; | ||
200 | } | ||
201 | |||
202 | eina_file_map_free(f, data); | ||
203 | eina_file_close(f); | ||
204 | |||
205 | return key; | ||
206 | |||
207 | on_error: | ||
208 | if (data) eina_file_map_free(f, data); | ||
209 | if (f) eina_file_close(f); | ||
210 | |||
211 | if (key) | ||
212 | { | ||
213 | if (key->certificate) | ||
214 | gnutls_x509_crt_deinit(key->certificate); | ||
215 | |||
216 | if (key->private_key) | ||
217 | gnutls_x509_privkey_deinit(key->private_key); | ||
218 | |||
219 | free(key); | ||
220 | } | ||
221 | |||
222 | # else /* ifdef HAVE_GNUTLS */ | ||
223 | /* Openssl private declarations */ | ||
224 | FILE *fp; | ||
225 | EVP_PKEY *pkey = NULL; | ||
226 | X509 *cert = NULL; | ||
227 | |||
228 | /* Load the X509 certificate in memory. */ | ||
229 | fp = fopen(certificate_file, "r"); | ||
230 | if (!fp) | ||
231 | return NULL; | ||
232 | |||
233 | cert = PEM_read_X509(fp, NULL, NULL, NULL); | ||
234 | fclose(fp); | ||
235 | if (!cert) | ||
236 | goto on_error; | ||
237 | |||
238 | /* Check the presence of the public key. Just in case. */ | ||
239 | pkey = X509_get_pubkey(cert); | ||
240 | if (!pkey) | ||
241 | goto on_error; | ||
242 | |||
243 | /* Load the private key in memory. */ | ||
244 | fp = fopen(private_key_file, "r"); | ||
245 | if (!fp) | ||
246 | goto on_error; | ||
247 | |||
248 | pkey = PEM_read_PrivateKey(fp, NULL, cb, NULL); | ||
249 | fclose(fp); | ||
250 | if (!pkey) | ||
251 | goto on_error; | ||
252 | |||
253 | /* Load the certificate and the private key in Eet_Key structure */ | ||
254 | key = malloc(sizeof(Eet_Key)); | ||
255 | if (!key) | ||
256 | goto on_error; | ||
257 | |||
258 | key->references = 1; | ||
259 | key->certificate = cert; | ||
260 | key->private_key = pkey; | ||
261 | |||
262 | return key; | ||
263 | |||
264 | on_error: | ||
265 | if (cert) | ||
266 | X509_free(cert); | ||
267 | |||
268 | if (pkey) | ||
269 | EVP_PKEY_free(pkey); | ||
270 | |||
271 | # endif /* ifdef HAVE_GNUTLS */ | ||
272 | #else | ||
273 | certificate_file = NULL; | ||
274 | private_key_file = NULL; | ||
275 | cb = NULL; | ||
276 | #endif /* ifdef HAVE_SIGNATURE */ | ||
277 | return NULL; | ||
278 | } /* eet_identity_open */ | ||
279 | |||
280 | EAPI void | ||
281 | eet_identity_close(Eet_Key *key) | ||
282 | { | ||
283 | #ifdef HAVE_SIGNATURE | ||
284 | if (!key || (key->references > 0)) | ||
285 | return; | ||
286 | |||
287 | # ifdef HAVE_GNUTLS | ||
288 | gnutls_x509_crt_deinit(key->certificate); | ||
289 | gnutls_x509_privkey_deinit(key->private_key); | ||
290 | # else /* ifdef HAVE_GNUTLS */ | ||
291 | X509_free(key->certificate); | ||
292 | EVP_PKEY_free(key->private_key); | ||
293 | # endif /* ifdef HAVE_GNUTLS */ | ||
294 | free(key); | ||
295 | #else | ||
296 | key = NULL; | ||
297 | #endif /* ifdef HAVE_SIGNATURE */ | ||
298 | } /* eet_identity_close */ | ||
299 | |||
300 | EAPI void | ||
301 | eet_identity_print(Eet_Key *key, | ||
302 | FILE *out) | ||
303 | { | ||
304 | #ifdef HAVE_SIGNATURE | ||
305 | # ifdef HAVE_GNUTLS | ||
306 | const char *names[6] = { | ||
307 | "Modulus", | ||
308 | "Public exponent", | ||
309 | "Private exponent", | ||
310 | "First prime", | ||
311 | "Second prime", | ||
312 | "Coefficient" | ||
313 | }; | ||
314 | int err = 0; | ||
315 | gnutls_datum_t data = { NULL, 0 }; | ||
316 | gnutls_datum_t rsa_raw[6]; | ||
317 | size_t size = 128; | ||
318 | char *res = NULL; | ||
319 | char buf[33]; | ||
320 | unsigned int i, j; | ||
321 | |||
322 | if (!key) | ||
323 | return; | ||
324 | |||
325 | if (key->private_key) | ||
326 | { | ||
327 | if (gnutls_x509_privkey_export_rsa_raw(key->private_key, | ||
328 | rsa_raw + 0, /* Modulus */ | ||
329 | rsa_raw + 1, /* Public exponent */ | ||
330 | rsa_raw + 2, /* Private exponent */ | ||
331 | rsa_raw + 3, /* First prime */ | ||
332 | rsa_raw + 4, /* Second prime */ | ||
333 | rsa_raw + 5)) /* Coefficient */ | ||
334 | goto on_error; | ||
335 | |||
336 | if (!(res = malloc(size))) | ||
337 | goto on_error; | ||
338 | |||
339 | fprintf(out, "Private Key:\n"); | ||
340 | buf[32] = '\0'; | ||
341 | |||
342 | for (i = 0; i < 6; i++) | ||
343 | { | ||
344 | while ((err = gnutls_hex_encode(rsa_raw + i, res, &size)) == | ||
345 | GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
346 | { | ||
347 | size += 128; | ||
348 | if (!(res = realloc(res, size))) | ||
349 | goto on_error; | ||
350 | } | ||
351 | if (err) | ||
352 | goto on_error; | ||
353 | |||
354 | fprintf(out, "\t%s:\n", names[i]); | ||
355 | for (j = 0; strlen(res) > j; j += 32) | ||
356 | { | ||
357 | snprintf(buf, 32, "%s", res + j); | ||
358 | fprintf(out, "\t\t%s\n", buf); | ||
359 | } | ||
360 | } | ||
361 | free(res); | ||
362 | res = NULL; | ||
363 | } | ||
364 | |||
365 | if (key->certificate) | ||
366 | { | ||
367 | fprintf(out, "Public certificate:\n"); | ||
368 | if (gnutls_x509_crt_print(key->certificate, GNUTLS_X509_CRT_FULL, | ||
369 | &data)) | ||
370 | goto on_error; | ||
371 | |||
372 | fprintf(out, "%s\n", data.data); | ||
373 | gnutls_free(data.data); | ||
374 | data.data = NULL; | ||
375 | } | ||
376 | |||
377 | on_error: | ||
378 | if (res) | ||
379 | free(res); | ||
380 | |||
381 | if (data.data) | ||
382 | gnutls_free(data.data); | ||
383 | |||
384 | return; | ||
385 | # else /* ifdef HAVE_GNUTLS */ | ||
386 | RSA *rsa; | ||
387 | DSA *dsa; | ||
388 | DH *dh; | ||
389 | |||
390 | if (!key) | ||
391 | return; | ||
392 | |||
393 | rsa = EVP_PKEY_get1_RSA(key->private_key); | ||
394 | if (rsa) | ||
395 | { | ||
396 | fprintf(out, "Private key (RSA):\n"); | ||
397 | RSA_print_fp(out, rsa, 0); | ||
398 | } | ||
399 | |||
400 | dsa = EVP_PKEY_get1_DSA(key->private_key); | ||
401 | if (dsa) | ||
402 | { | ||
403 | fprintf(out, "Private key (DSA):\n"); | ||
404 | DSA_print_fp(out, dsa, 0); | ||
405 | } | ||
406 | |||
407 | dh = EVP_PKEY_get1_DH(key->private_key); | ||
408 | if (dh) | ||
409 | { | ||
410 | fprintf(out, "Private key (DH):\n"); | ||
411 | DHparams_print_fp(out, dh); | ||
412 | } | ||
413 | |||
414 | fprintf(out, "Public certificate:\n"); | ||
415 | X509_print_fp(out, key->certificate); | ||
416 | # endif /* ifdef HAVE_GNUTLS */ | ||
417 | #else /* ifdef HAVE_SIGNATURE */ | ||
418 | key = NULL; | ||
419 | out = NULL; | ||
420 | ERR("You need to compile signature support in EET."); | ||
421 | #endif /* ifdef HAVE_SIGNATURE */ | ||
422 | } /* eet_identity_print */ | ||
423 | |||
424 | void | ||
425 | eet_identity_ref(Eet_Key *key) | ||
426 | { | ||
427 | if (!key) | ||
428 | return; | ||
429 | |||
430 | key->references++; | ||
431 | } /* eet_identity_ref */ | ||
432 | |||
433 | void | ||
434 | eet_identity_unref(Eet_Key *key) | ||
435 | { | ||
436 | if (!key) | ||
437 | return; | ||
438 | |||
439 | key->references--; | ||
440 | eet_identity_close(key); | ||
441 | } /* eet_identity_unref */ | ||
442 | |||
443 | void * | ||
444 | eet_identity_compute_sha1(const void *data_base, | ||
445 | unsigned int data_length, | ||
446 | int *sha1_length) | ||
447 | { | ||
448 | void *result; | ||
449 | |||
450 | #ifdef HAVE_SIGNATURE | ||
451 | # ifdef HAVE_GNUTLS | ||
452 | result = malloc(gcry_md_get_algo_dlen(GCRY_MD_SHA1)); | ||
453 | if (!result) | ||
454 | return NULL; | ||
455 | |||
456 | gcry_md_hash_buffer(GCRY_MD_SHA1, result, data_base, data_length); | ||
457 | if (sha1_length) | ||
458 | *sha1_length = gcry_md_get_algo_dlen(GCRY_MD_SHA1); | ||
459 | |||
460 | # else /* ifdef HAVE_GNUTLS */ | ||
461 | # ifdef HAVE_OPENSSL | ||
462 | result = malloc(SHA_DIGEST_LENGTH); | ||
463 | if (!result) | ||
464 | return NULL; | ||
465 | |||
466 | SHA1(data_base, data_length, result); | ||
467 | if (sha1_length) | ||
468 | *sha1_length = SHA_DIGEST_LENGTH; | ||
469 | |||
470 | # else /* ifdef HAVE_OPENSSL */ | ||
471 | result = NULL; | ||
472 | # endif /* ifdef HAVE_OPENSSL */ | ||
473 | # endif /* ifdef HAVE_GNUTLS */ | ||
474 | #else /* ifdef HAVE_SIGNATURE */ | ||
475 | data_base = NULL; | ||
476 | data_length = 0; | ||
477 | sha1_length = NULL; | ||
478 | result = NULL; | ||
479 | #endif /* ifdef HAVE_SIGNATURE */ | ||
480 | |||
481 | return result; | ||
482 | } /* eet_identity_compute_sha1 */ | ||
483 | |||
484 | Eet_Error | ||
485 | eet_identity_sign(FILE *fp, | ||
486 | Eet_Key *key) | ||
487 | { | ||
488 | #ifdef HAVE_SIGNATURE | ||
489 | Eet_Error err = EET_ERROR_NONE; | ||
490 | struct stat st_buf; | ||
491 | void *data; | ||
492 | int fd; | ||
493 | int head[3]; | ||
494 | unsigned char *sign = NULL; | ||
495 | unsigned char *cert = NULL; | ||
496 | # ifdef HAVE_GNUTLS | ||
497 | gnutls_datum_t datum = { NULL, 0 }; | ||
498 | size_t sign_len = 0; | ||
499 | size_t cert_len = 0; | ||
500 | # else /* ifdef HAVE_GNUTLS */ | ||
501 | EVP_MD_CTX md_ctx; | ||
502 | unsigned int sign_len = 0; | ||
503 | int cert_len = 0; | ||
504 | # endif /* ifdef HAVE_GNUTLS */ | ||
505 | |||
506 | /* A few check and flush pending write. */ | ||
507 | if (!fp || !key || !key->certificate || !key->private_key) | ||
508 | return EET_ERROR_BAD_OBJECT; | ||
509 | |||
510 | /* Get the file size. */ | ||
511 | fd = fileno(fp); | ||
512 | if (fd < 0) | ||
513 | return EET_ERROR_BAD_OBJECT; | ||
514 | |||
515 | if (fstat(fd, &st_buf) < 0) | ||
516 | return EET_ERROR_MMAP_FAILED; | ||
517 | |||
518 | /* let's make mmap safe and just get 0 pages for IO erro */ | ||
519 | eina_mmap_safety_enabled_set(EINA_TRUE); | ||
520 | |||
521 | /* Map the file in memory. */ | ||
522 | data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); | ||
523 | if (data == MAP_FAILED) | ||
524 | return EET_ERROR_MMAP_FAILED; | ||
525 | |||
526 | # ifdef HAVE_GNUTLS | ||
527 | datum.data = data; | ||
528 | datum.size = st_buf.st_size; | ||
529 | |||
530 | /* Get the signature length */ | ||
531 | if (gnutls_x509_privkey_sign_data(key->private_key, GNUTLS_DIG_SHA1, 0, | ||
532 | &datum, sign, &sign_len) && | ||
533 | !sign_len) | ||
534 | { | ||
535 | err = EET_ERROR_SIGNATURE_FAILED; | ||
536 | goto on_error; | ||
537 | } | ||
538 | |||
539 | /* Get the signature */ | ||
540 | sign = malloc(sign_len); | ||
541 | if (!sign || | ||
542 | gnutls_x509_privkey_sign_data(key->private_key, GNUTLS_DIG_SHA1, 0, | ||
543 | &datum, | ||
544 | sign, &sign_len)) | ||
545 | { | ||
546 | if (!sign) | ||
547 | err = EET_ERROR_OUT_OF_MEMORY; | ||
548 | else | ||
549 | err = EET_ERROR_SIGNATURE_FAILED; | ||
550 | |||
551 | goto on_error; | ||
552 | } | ||
553 | |||
554 | /* Get the certificate length */ | ||
555 | if (gnutls_x509_crt_export(key->certificate, GNUTLS_X509_FMT_DER, cert, | ||
556 | &cert_len) && | ||
557 | !cert_len) | ||
558 | { | ||
559 | err = EET_ERROR_SIGNATURE_FAILED; | ||
560 | goto on_error; | ||
561 | } | ||
562 | |||
563 | /* Get the certificate */ | ||
564 | cert = malloc(cert_len); | ||
565 | if (!cert || | ||
566 | gnutls_x509_crt_export(key->certificate, GNUTLS_X509_FMT_DER, cert, | ||
567 | &cert_len)) | ||
568 | { | ||
569 | if (!cert) | ||
570 | err = EET_ERROR_OUT_OF_MEMORY; | ||
571 | else | ||
572 | err = EET_ERROR_SIGNATURE_FAILED; | ||
573 | |||
574 | goto on_error; | ||
575 | } | ||
576 | |||
577 | # else /* ifdef HAVE_GNUTLS */ | ||
578 | sign_len = EVP_PKEY_size(key->private_key); | ||
579 | sign = malloc(sign_len); | ||
580 | if (!sign) | ||
581 | { | ||
582 | err = EET_ERROR_OUT_OF_MEMORY; | ||
583 | goto on_error; | ||
584 | } | ||
585 | |||
586 | /* Do the signature. */ | ||
587 | EVP_SignInit(&md_ctx, EVP_sha1()); | ||
588 | EVP_SignUpdate(&md_ctx, data, st_buf.st_size); | ||
589 | err = EVP_SignFinal(&md_ctx, | ||
590 | sign, | ||
591 | (unsigned int *)&sign_len, | ||
592 | key->private_key); | ||
593 | if (err != 1) | ||
594 | { | ||
595 | ERR_print_errors_fp(stdout); | ||
596 | err = EET_ERROR_SIGNATURE_FAILED; | ||
597 | goto on_error; | ||
598 | } | ||
599 | |||
600 | /* Give me the der (binary form for X509). */ | ||
601 | cert_len = i2d_X509(key->certificate, &cert); | ||
602 | if (cert_len < 0) | ||
603 | { | ||
604 | ERR_print_errors_fp(stdout); | ||
605 | err = EET_ERROR_X509_ENCODING_FAILED; | ||
606 | goto on_error; | ||
607 | } | ||
608 | |||
609 | # endif /* ifdef HAVE_GNUTLS */ | ||
610 | /* Append the signature at the end of the file. */ | ||
611 | head[0] = (int)htonl ((unsigned int)EET_MAGIC_SIGN); | ||
612 | head[1] = (int)htonl ((unsigned int)sign_len); | ||
613 | head[2] = (int)htonl ((unsigned int)cert_len); | ||
614 | |||
615 | if (fwrite(head, sizeof(head), 1, fp) != 1) | ||
616 | { | ||
617 | err = EET_ERROR_WRITE_ERROR; | ||
618 | goto on_error; | ||
619 | } | ||
620 | |||
621 | if (fwrite(sign, sign_len, 1, fp) != 1) | ||
622 | { | ||
623 | err = EET_ERROR_WRITE_ERROR; | ||
624 | goto on_error; | ||
625 | } | ||
626 | |||
627 | if (fwrite(cert, cert_len, 1, fp) != 1) | ||
628 | { | ||
629 | err = EET_ERROR_WRITE_ERROR; | ||
630 | goto on_error; | ||
631 | } | ||
632 | |||
633 | on_error: | ||
634 | # ifdef HAVE_GNUTLS | ||
635 | if (cert) | ||
636 | free(cert); | ||
637 | |||
638 | # else /* ifdef HAVE_GNUTLS */ | ||
639 | if (cert) | ||
640 | OPENSSL_free(cert); | ||
641 | |||
642 | # endif /* ifdef HAVE_GNUTLS */ | ||
643 | if (sign) | ||
644 | free(sign); | ||
645 | |||
646 | munmap(data, st_buf.st_size); | ||
647 | return err; | ||
648 | #else /* ifdef HAVE_SIGNATURE */ | ||
649 | fp = NULL; | ||
650 | key = NULL; | ||
651 | return EET_ERROR_NOT_IMPLEMENTED; | ||
652 | #endif /* ifdef HAVE_SIGNATURE */ | ||
653 | } /* eet_identity_sign */ | ||
654 | |||
655 | const void * | ||
656 | eet_identity_check(const void *data_base, | ||
657 | unsigned int data_length, | ||
658 | void **sha1, | ||
659 | int *sha1_length, | ||
660 | const void *signature_base, | ||
661 | unsigned int signature_length, | ||
662 | const void **raw_signature_base, | ||
663 | unsigned int *raw_signature_length, | ||
664 | int *x509_length) | ||
665 | { | ||
666 | #ifdef HAVE_SIGNATURE | ||
667 | const int *header = signature_base; | ||
668 | const unsigned char *sign; | ||
669 | const unsigned char *cert_der; | ||
670 | int sign_len; | ||
671 | int cert_len; | ||
672 | int magic; | ||
673 | |||
674 | /* At least the header size */ | ||
675 | if (signature_length < sizeof(int) * 3) | ||
676 | return NULL; | ||
677 | |||
678 | /* Get the header */ | ||
679 | magic = ntohl(header[0]); | ||
680 | sign_len = ntohl(header[1]); | ||
681 | cert_len = ntohl(header[2]); | ||
682 | |||
683 | /* Verify the header */ | ||
684 | if (magic != EET_MAGIC_SIGN) | ||
685 | return NULL; | ||
686 | |||
687 | if (sign_len + cert_len + sizeof(int) * 3 > signature_length) | ||
688 | return NULL; | ||
689 | |||
690 | /* Update the signature and certificate pointer */ | ||
691 | sign = (unsigned char *)signature_base + sizeof(int) * 3; | ||
692 | cert_der = sign + sign_len; | ||
693 | |||
694 | # ifdef HAVE_GNUTLS | ||
695 | gnutls_x509_crt_t cert; | ||
696 | gnutls_datum_t datum; | ||
697 | gnutls_datum_t signature; | ||
698 | # if EET_USE_NEW_GNUTLS_API | ||
699 | unsigned char *hash; | ||
700 | gcry_md_hd_t md; | ||
701 | int err; | ||
702 | # endif /* if EET_USE_NEW_GNUTLS_API */ | ||
703 | |||
704 | /* Create an understanding certificate structure for gnutls */ | ||
705 | datum.data = (void *)cert_der; | ||
706 | datum.size = cert_len; | ||
707 | gnutls_x509_crt_init(&cert); | ||
708 | gnutls_x509_crt_import(cert, &datum, GNUTLS_X509_FMT_DER); | ||
709 | |||
710 | signature.data = (void *)sign; | ||
711 | signature.size = sign_len; | ||
712 | |||
713 | /* Verify the signature */ | ||
714 | # if EET_USE_NEW_GNUTLS_API | ||
715 | /* | ||
716 | I am waiting for my patch being accepted in GnuTLS release. | ||
717 | But we now have a way to prevent double computation of SHA1. | ||
718 | */ | ||
719 | err = gcry_md_open (&md, GCRY_MD_SHA1, 0); | ||
720 | if (err < 0) | ||
721 | return NULL; | ||
722 | |||
723 | gcry_md_write(md, data_base, data_length); | ||
724 | |||
725 | hash = gcry_md_read(md, GCRY_MD_SHA1); | ||
726 | if (!hash) | ||
727 | { | ||
728 | gcry_md_close(md); | ||
729 | return NULL; | ||
730 | } | ||
731 | |||
732 | datum.size = gcry_md_get_algo_dlen(GCRY_MD_SHA1); | ||
733 | datum.data = hash; | ||
734 | |||
735 | if (!gnutls_x509_crt_verify_hash(cert, 0, &datum, &signature)) | ||
736 | { | ||
737 | gcry_md_close(md); | ||
738 | return NULL; | ||
739 | } | ||
740 | |||
741 | if (sha1) | ||
742 | { | ||
743 | *sha1 = malloc(datum.size); | ||
744 | if (!*sha1) | ||
745 | { | ||
746 | gcry_md_close(md); | ||
747 | return NULL; | ||
748 | } | ||
749 | |||
750 | memcpy(*sha1, hash, datum.size); | ||
751 | *sha1_length = datum.size; | ||
752 | } | ||
753 | |||
754 | gcry_md_close(md); | ||
755 | # else /* if EET_USE_NEW_GNUTLS_API */ | ||
756 | datum.data = (void *)data_base; | ||
757 | datum.size = data_length; | ||
758 | |||
759 | if (!gnutls_x509_crt_verify_data(cert, 0, &datum, &signature)) | ||
760 | return NULL; | ||
761 | |||
762 | if (sha1) | ||
763 | { | ||
764 | *sha1 = NULL; | ||
765 | *sha1_length = -1; | ||
766 | } | ||
767 | |||
768 | # endif /* if EET_USE_NEW_GNUTLS_API */ | ||
769 | gnutls_x509_crt_deinit(cert); | ||
770 | |||
771 | # else /* ifdef HAVE_GNUTLS */ | ||
772 | const unsigned char *tmp; | ||
773 | EVP_PKEY *pkey; | ||
774 | X509 *x509; | ||
775 | EVP_MD_CTX md_ctx; | ||
776 | int err; | ||
777 | |||
778 | /* Strange but d2i_X509 seems to put 0 all over the place. */ | ||
779 | tmp = alloca(cert_len); | ||
780 | memcpy((char *)tmp, cert_der, cert_len); | ||
781 | x509 = d2i_X509(NULL, &tmp, cert_len); | ||
782 | if (!x509) | ||
783 | return NULL; | ||
784 | |||
785 | /* Get public key - eay */ | ||
786 | pkey = X509_get_pubkey(x509); | ||
787 | if (!pkey) | ||
788 | { | ||
789 | X509_free(x509); | ||
790 | return NULL; | ||
791 | } | ||
792 | |||
793 | /* Verify the signature */ | ||
794 | EVP_VerifyInit(&md_ctx, EVP_sha1()); | ||
795 | EVP_VerifyUpdate(&md_ctx, data_base, data_length); | ||
796 | err = EVP_VerifyFinal(&md_ctx, sign, sign_len, pkey); | ||
797 | |||
798 | X509_free(x509); | ||
799 | EVP_PKEY_free(pkey); | ||
800 | |||
801 | if (sha1) | ||
802 | { | ||
803 | *sha1 = NULL; | ||
804 | *sha1_length = -1; | ||
805 | } | ||
806 | |||
807 | if (err != 1) | ||
808 | return NULL; | ||
809 | |||
810 | # endif /* ifdef HAVE_GNUTLS */ | ||
811 | if (x509_length) | ||
812 | *x509_length = cert_len; | ||
813 | |||
814 | if (raw_signature_base) | ||
815 | *raw_signature_base = sign; | ||
816 | |||
817 | if (raw_signature_length) | ||
818 | *raw_signature_length = sign_len; | ||
819 | |||
820 | return cert_der; | ||
821 | #else /* ifdef HAVE_SIGNATURE */ | ||
822 | data_base = NULL; | ||
823 | data_length = 0; | ||
824 | sha1 = NULL; | ||
825 | sha1_length = NULL; | ||
826 | signature_base = NULL; | ||
827 | signature_length = 0; | ||
828 | raw_signature_base = NULL; | ||
829 | raw_signature_length = NULL; | ||
830 | x509_length = NULL; | ||
831 | return NULL; | ||
832 | #endif /* ifdef HAVE_SIGNATURE */ | ||
833 | } /* eet_identity_check */ | ||
834 | |||
835 | EAPI void | ||
836 | eet_identity_certificate_print(const unsigned char *certificate, | ||
837 | int der_length, | ||
838 | FILE *out) | ||
839 | { | ||
840 | #ifdef HAVE_SIGNATURE | ||
841 | if (!certificate || !out || der_length <= 0) | ||
842 | { | ||
843 | ERR("No certificate provided."); | ||
844 | return; | ||
845 | } | ||
846 | |||
847 | # ifdef HAVE_GNUTLS | ||
848 | gnutls_datum_t datum; | ||
849 | gnutls_x509_crt_t cert; | ||
850 | |||
851 | /* Create an understanding certificate structure for gnutls */ | ||
852 | datum.data = (void *)certificate; | ||
853 | datum.size = der_length; | ||
854 | if (gnutls_x509_crt_init(&cert)) | ||
855 | goto on_error; | ||
856 | |||
857 | if (gnutls_x509_crt_import(cert, &datum, GNUTLS_X509_FMT_DER)) | ||
858 | goto on_error; | ||
859 | |||
860 | /* Pretty print the certificate */ | ||
861 | datum.data = NULL; | ||
862 | datum.size = 0; | ||
863 | if (gnutls_x509_crt_print(cert, GNUTLS_X509_CRT_FULL, &datum)) | ||
864 | goto on_error; | ||
865 | |||
866 | INF("Public certificate :"); | ||
867 | INF("%s", datum.data); | ||
868 | |||
869 | on_error: | ||
870 | if (datum.data) | ||
871 | gnutls_free(datum.data); | ||
872 | |||
873 | gnutls_x509_crt_deinit(cert); | ||
874 | # else /* ifdef HAVE_GNUTLS */ | ||
875 | const unsigned char *tmp; | ||
876 | X509 *x509; | ||
877 | |||
878 | /* Strange but d2i_X509 seems to put 0 all over the place. */ | ||
879 | tmp = alloca(der_length); | ||
880 | memcpy((char *)tmp, certificate, der_length); | ||
881 | x509 = d2i_X509(NULL, &tmp, der_length); | ||
882 | if (!x509) | ||
883 | { | ||
884 | INF("Not a valid certificate."); | ||
885 | return; | ||
886 | } | ||
887 | |||
888 | INF("Public certificate :"); | ||
889 | X509_print_fp(out, x509); | ||
890 | |||
891 | X509_free(x509); | ||
892 | # endif /* ifdef HAVE_GNUTLS */ | ||
893 | #else /* ifdef HAVE_SIGNATURE */ | ||
894 | certificate = NULL; | ||
895 | der_length = 0; | ||
896 | out = NULL; | ||
897 | ERR("You need to compile signature support in EET."); | ||
898 | #endif /* ifdef HAVE_SIGNATURE */ | ||
899 | } /* eet_identity_certificate_print */ | ||
900 | |||
901 | Eet_Error | ||
902 | eet_cipher(const void *data, | ||
903 | unsigned int size, | ||
904 | const char *key, | ||
905 | unsigned int length, | ||
906 | void **result, | ||
907 | unsigned int *result_length) | ||
908 | { | ||
909 | #ifdef HAVE_CIPHER | ||
910 | /* Cipher declarations */ | ||
911 | unsigned int *ret = NULL; | ||
912 | unsigned char iv[MAX_IV_LEN]; | ||
913 | unsigned char ik[MAX_KEY_LEN]; | ||
914 | unsigned char key_material[MAX_IV_LEN + MAX_KEY_LEN]; | ||
915 | unsigned int salt; | ||
916 | unsigned int tmp = 0; | ||
917 | int crypted_length; | ||
918 | int opened = 0; | ||
919 | # ifdef HAVE_GNUTLS | ||
920 | /* Gcrypt declarations */ | ||
921 | gcry_error_t err = 0; | ||
922 | gcry_cipher_hd_t cipher; | ||
923 | # else /* ifdef HAVE_GNUTLS */ | ||
924 | /* Openssl declarations*/ | ||
925 | EVP_CIPHER_CTX ctx; | ||
926 | unsigned int *buffer; | ||
927 | int tmp_len; | ||
928 | # endif /* ifdef HAVE_GNUTLS */ | ||
929 | |||
930 | # ifdef HAVE_GNUTLS | ||
931 | /* Gcrypt salt generation */ | ||
932 | gcry_create_nonce((unsigned char *)&salt, sizeof(salt)); | ||
933 | # else /* ifdef HAVE_GNUTLS */ | ||
934 | /* Openssl salt generation */ | ||
935 | if (!RAND_bytes((unsigned char *)&salt, sizeof (unsigned int))) | ||
936 | return EET_ERROR_PRNG_NOT_SEEDED; | ||
937 | |||
938 | # endif /* ifdef HAVE_GNUTLS */ | ||
939 | |||
940 | eet_pbkdf2_sha1(key, | ||
941 | length, | ||
942 | (unsigned char *)&salt, | ||
943 | sizeof(unsigned int), | ||
944 | 2048, | ||
945 | key_material, | ||
946 | MAX_KEY_LEN + MAX_IV_LEN); | ||
947 | |||
948 | memcpy(iv, key_material, MAX_IV_LEN); | ||
949 | memcpy(ik, key_material + MAX_IV_LEN, MAX_KEY_LEN); | ||
950 | |||
951 | memset(key_material, 0, sizeof (key_material)); | ||
952 | |||
953 | crypted_length = ((((size + sizeof (unsigned int)) >> 5) + 1) << 5); | ||
954 | ret = malloc(crypted_length + sizeof(unsigned int)); | ||
955 | if (!ret) | ||
956 | { | ||
957 | memset(iv, 0, sizeof (iv)); | ||
958 | memset(ik, 0, sizeof (ik)); | ||
959 | memset(&salt, 0, sizeof (salt)); | ||
960 | return EET_ERROR_OUT_OF_MEMORY; | ||
961 | } | ||
962 | |||
963 | *ret = salt; | ||
964 | memset(&salt, 0, sizeof (salt)); | ||
965 | tmp = htonl(size); | ||
966 | |||
967 | # ifdef HAVE_GNUTLS | ||
968 | *(ret + 1) = tmp; | ||
969 | memcpy(ret + 2, data, size); | ||
970 | |||
971 | /* Gcrypt create the corresponding cipher | ||
972 | AES with a 256 bit key, Cipher Block Chaining mode */ | ||
973 | err = gcry_cipher_open(&cipher, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0); | ||
974 | if (err) | ||
975 | goto on_error; | ||
976 | |||
977 | opened = 1; | ||
978 | err = gcry_cipher_setiv(cipher, iv, MAX_IV_LEN); | ||
979 | if (err) | ||
980 | goto on_error; | ||
981 | |||
982 | err = gcry_cipher_setkey(cipher, ik, MAX_KEY_LEN); | ||
983 | if (err) | ||
984 | goto on_error; | ||
985 | |||
986 | memset(iv, 0, sizeof (iv)); | ||
987 | memset(ik, 0, sizeof (ik)); | ||
988 | |||
989 | /* Gcrypt encrypt */ | ||
990 | err = gcry_cipher_encrypt(cipher, | ||
991 | (unsigned char *)(ret + 1), | ||
992 | crypted_length, | ||
993 | NULL, | ||
994 | 0); | ||
995 | if (err) | ||
996 | goto on_error; | ||
997 | |||
998 | /* Gcrypt close the cipher */ | ||
999 | gcry_cipher_close(cipher); | ||
1000 | # else /* ifdef HAVE_GNUTLS */ | ||
1001 | buffer = alloca(crypted_length); | ||
1002 | *buffer = tmp; | ||
1003 | |||
1004 | memcpy(buffer + 1, data, size); | ||
1005 | |||
1006 | /* Openssl create the corresponding cipher | ||
1007 | AES with a 256 bit key, Cipher Block Chaining mode */ | ||
1008 | EVP_CIPHER_CTX_init(&ctx); | ||
1009 | if (!EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, ik, iv)) | ||
1010 | goto on_error; | ||
1011 | |||
1012 | opened = 1; | ||
1013 | |||
1014 | memset(iv, 0, sizeof (iv)); | ||
1015 | memset(ik, 0, sizeof (ik)); | ||
1016 | |||
1017 | /* Openssl encrypt */ | ||
1018 | if (!EVP_EncryptUpdate(&ctx, (unsigned char *)(ret + 1), &tmp_len, | ||
1019 | (unsigned char *)buffer, | ||
1020 | size + sizeof(unsigned int))) | ||
1021 | goto on_error; | ||
1022 | |||
1023 | /* Openssl close the cipher */ | ||
1024 | if (!EVP_EncryptFinal_ex(&ctx, ((unsigned char *)(ret + 1)) + tmp_len, | ||
1025 | &tmp_len)) | ||
1026 | goto on_error; | ||
1027 | |||
1028 | EVP_CIPHER_CTX_cleanup(&ctx); | ||
1029 | # endif /* ifdef HAVE_GNUTLS */ | ||
1030 | |||
1031 | /* Set return values */ | ||
1032 | if (result_length) | ||
1033 | *result_length = crypted_length + sizeof(unsigned int); | ||
1034 | |||
1035 | if (result) | ||
1036 | *result = ret; | ||
1037 | else | ||
1038 | free(ret); | ||
1039 | |||
1040 | return EET_ERROR_NONE; | ||
1041 | |||
1042 | on_error: | ||
1043 | memset(iv, 0, sizeof (iv)); | ||
1044 | memset(ik, 0, sizeof (ik)); | ||
1045 | |||
1046 | # ifdef HAVE_GNUTLS | ||
1047 | /* Gcrypt error */ | ||
1048 | if (opened) | ||
1049 | gcry_cipher_close(cipher); | ||
1050 | |||
1051 | # else /* ifdef HAVE_GNUTLS */ | ||
1052 | /* Openssl error */ | ||
1053 | if (opened) | ||
1054 | EVP_CIPHER_CTX_cleanup(&ctx); | ||
1055 | |||
1056 | # endif /* ifdef HAVE_GNUTLS */ | ||
1057 | /* General error */ | ||
1058 | free(ret); | ||
1059 | if (result) | ||
1060 | *result = NULL; | ||
1061 | |||
1062 | if (result_length) | ||
1063 | *result_length = 0; | ||
1064 | |||
1065 | return EET_ERROR_ENCRYPT_FAILED; | ||
1066 | #else /* ifdef HAVE_CIPHER */ | ||
1067 | /* Cipher not supported */ | ||
1068 | (void)data; | ||
1069 | (void)size; | ||
1070 | (void)key; | ||
1071 | (void)length; | ||
1072 | (void)result; | ||
1073 | (void)result_length; | ||
1074 | return EET_ERROR_NOT_IMPLEMENTED; | ||
1075 | #endif /* ifdef HAVE_CIPHER */ | ||
1076 | } /* eet_cipher */ | ||
1077 | |||
1078 | Eet_Error | ||
1079 | eet_decipher(const void *data, | ||
1080 | unsigned int size, | ||
1081 | const char *key, | ||
1082 | unsigned int length, | ||
1083 | void **result, | ||
1084 | unsigned int *result_length) | ||
1085 | { | ||
1086 | #ifdef HAVE_CIPHER | ||
1087 | const unsigned int *over = data; | ||
1088 | unsigned int *ret = NULL; | ||
1089 | unsigned char ik[MAX_KEY_LEN]; | ||
1090 | unsigned char iv[MAX_IV_LEN]; | ||
1091 | unsigned char key_material[MAX_KEY_LEN + MAX_IV_LEN]; | ||
1092 | unsigned int salt; | ||
1093 | int tmp_len; | ||
1094 | int tmp = 0; | ||
1095 | |||
1096 | /* At least the salt and an AES block */ | ||
1097 | if (size < sizeof(unsigned int) + 16) | ||
1098 | return EET_ERROR_BAD_OBJECT; | ||
1099 | |||
1100 | /* Get the salt */ | ||
1101 | salt = *over; | ||
1102 | |||
1103 | /* Generate the iv and the key with the salt */ | ||
1104 | eet_pbkdf2_sha1(key, length, (unsigned char *)&salt, | ||
1105 | sizeof(unsigned int), 2048, key_material, | ||
1106 | MAX_KEY_LEN + MAX_IV_LEN); | ||
1107 | |||
1108 | memcpy(iv, key_material, MAX_IV_LEN); | ||
1109 | memcpy(ik, key_material + MAX_IV_LEN, MAX_KEY_LEN); | ||
1110 | |||
1111 | memset(key_material, 0, sizeof (key_material)); | ||
1112 | memset(&salt, 0, sizeof (salt)); | ||
1113 | |||
1114 | /* Align to AES block size if size is not align */ | ||
1115 | tmp_len = size - sizeof (unsigned int); | ||
1116 | if ((tmp_len & 0x1F) != 0) | ||
1117 | goto on_error; | ||
1118 | |||
1119 | ret = malloc(tmp_len); | ||
1120 | if (!ret) | ||
1121 | goto on_error; | ||
1122 | |||
1123 | # ifdef HAVE_GNUTLS | ||
1124 | gcry_error_t err = 0; | ||
1125 | gcry_cipher_hd_t cipher; | ||
1126 | |||
1127 | /* Gcrypt create the corresponding cipher */ | ||
1128 | err = gcry_cipher_open(&cipher, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0); | ||
1129 | if (err) | ||
1130 | return EET_ERROR_DECRYPT_FAILED; | ||
1131 | |||
1132 | err = gcry_cipher_setiv(cipher, iv, MAX_IV_LEN); | ||
1133 | if (err) | ||
1134 | goto on_error; | ||
1135 | |||
1136 | err = gcry_cipher_setkey(cipher, ik, MAX_KEY_LEN); | ||
1137 | if (err) | ||
1138 | goto on_error; | ||
1139 | |||
1140 | memset(iv, 0, sizeof (iv)); | ||
1141 | memset(ik, 0, sizeof (ik)); | ||
1142 | |||
1143 | /* Gcrypt decrypt */ | ||
1144 | err = gcry_cipher_decrypt(cipher, ret, tmp_len, | ||
1145 | ((unsigned int *)data) + 1, tmp_len); | ||
1146 | if (err) | ||
1147 | goto on_error; | ||
1148 | |||
1149 | /* Gcrypt close the cipher */ | ||
1150 | gcry_cipher_close(cipher); | ||
1151 | |||
1152 | # else /* ifdef HAVE_GNUTLS */ | ||
1153 | EVP_CIPHER_CTX ctx; | ||
1154 | int opened = 0; | ||
1155 | |||
1156 | /* Openssl create the corresponding cipher */ | ||
1157 | EVP_CIPHER_CTX_init(&ctx); | ||
1158 | opened = 1; | ||
1159 | |||
1160 | if (!EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, ik, iv)) | ||
1161 | goto on_error; | ||
1162 | |||
1163 | memset(iv, 0, sizeof (iv)); | ||
1164 | memset(ik, 0, sizeof (ik)); | ||
1165 | |||
1166 | /* Openssl decrypt */ | ||
1167 | if (!EVP_DecryptUpdate(&ctx, (unsigned char *)ret, &tmp, | ||
1168 | (unsigned char *)(over + 1), tmp_len)) | ||
1169 | goto on_error; | ||
1170 | |||
1171 | /* Openssl close the cipher*/ | ||
1172 | EVP_CIPHER_CTX_cleanup(&ctx); | ||
1173 | # endif /* ifdef HAVE_GNUTLS */ | ||
1174 | /* Get the decrypted data size */ | ||
1175 | tmp = *ret; | ||
1176 | tmp = ntohl(tmp); | ||
1177 | if (tmp > tmp_len) | ||
1178 | goto on_error; | ||
1179 | |||
1180 | /* Update the return values */ | ||
1181 | if (result_length) | ||
1182 | *result_length = tmp; | ||
1183 | |||
1184 | if (result) | ||
1185 | { | ||
1186 | *result = NULL; | ||
1187 | *result = malloc(tmp); | ||
1188 | if (!*result) | ||
1189 | goto on_error; | ||
1190 | |||
1191 | memcpy(*result, ret + 1, tmp); | ||
1192 | } | ||
1193 | |||
1194 | free(ret); | ||
1195 | |||
1196 | return EET_ERROR_NONE; | ||
1197 | |||
1198 | on_error: | ||
1199 | memset(iv, 0, sizeof (iv)); | ||
1200 | memset(ik, 0, sizeof (ik)); | ||
1201 | |||
1202 | # ifdef HAVE_GNUTLS | ||
1203 | # else | ||
1204 | if (opened) | ||
1205 | EVP_CIPHER_CTX_cleanup(&ctx); | ||
1206 | |||
1207 | # endif /* ifdef HAVE_GNUTLS */ | ||
1208 | if (result) | ||
1209 | *result = NULL; | ||
1210 | |||
1211 | if (result_length) | ||
1212 | *result_length = 0; | ||
1213 | |||
1214 | if (ret) | ||
1215 | free(ret); | ||
1216 | |||
1217 | return EET_ERROR_DECRYPT_FAILED; | ||
1218 | #else /* ifdef HAVE_CIPHER */ | ||
1219 | (void)data; | ||
1220 | (void)size; | ||
1221 | (void)key; | ||
1222 | (void)length; | ||
1223 | (void)result; | ||
1224 | (void)result_length; | ||
1225 | return EET_ERROR_NOT_IMPLEMENTED; | ||
1226 | #endif /* ifdef HAVE_CIPHER */ | ||
1227 | } /* eet_decipher */ | ||
1228 | |||
1229 | #ifdef HAVE_CIPHER | ||
1230 | # ifdef HAVE_GNUTLS | ||
1231 | static Eet_Error | ||
1232 | eet_hmac_sha1(const void *key, | ||
1233 | size_t key_len, | ||
1234 | const void *data, | ||
1235 | size_t data_len, | ||
1236 | unsigned char *res) | ||
1237 | { | ||
1238 | size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1); | ||
1239 | gcry_md_hd_t mdh; | ||
1240 | unsigned char *hash; | ||
1241 | gpg_error_t err; | ||
1242 | |||
1243 | err = gcry_md_open(&mdh, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); | ||
1244 | if (err != GPG_ERR_NO_ERROR) | ||
1245 | return 1; | ||
1246 | |||
1247 | err = gcry_md_setkey(mdh, key, key_len); | ||
1248 | if (err != GPG_ERR_NO_ERROR) | ||
1249 | { | ||
1250 | gcry_md_close(mdh); | ||
1251 | return 1; | ||
1252 | } | ||
1253 | |||
1254 | gcry_md_write(mdh, data, data_len); | ||
1255 | |||
1256 | hash = gcry_md_read(mdh, GCRY_MD_SHA1); | ||
1257 | if (!hash) | ||
1258 | { | ||
1259 | gcry_md_close(mdh); | ||
1260 | return 1; | ||
1261 | } | ||
1262 | |||
1263 | memcpy(res, hash, hlen); | ||
1264 | |||
1265 | gcry_md_close(mdh); | ||
1266 | |||
1267 | return 0; | ||
1268 | } /* eet_hmac_sha1 */ | ||
1269 | |||
1270 | # endif /* ifdef HAVE_GNUTLS */ | ||
1271 | |||
1272 | static Eet_Error | ||
1273 | eet_pbkdf2_sha1(const char *key, | ||
1274 | int key_len, | ||
1275 | const unsigned char *salt, | ||
1276 | unsigned int salt_len, | ||
1277 | int iter, | ||
1278 | unsigned char *res, | ||
1279 | int res_len) | ||
1280 | { | ||
1281 | unsigned char digest[20]; | ||
1282 | unsigned char tab[4]; | ||
1283 | unsigned char *p = res; | ||
1284 | unsigned char *buf; | ||
1285 | unsigned long i; | ||
1286 | int digest_len = 20; | ||
1287 | int len = res_len; | ||
1288 | int tmp_len; | ||
1289 | int j, k; | ||
1290 | # ifdef HAVE_GNUTLS | ||
1291 | # else | ||
1292 | HMAC_CTX hctx; | ||
1293 | # endif /* ifdef HAVE_GNUTLS */ | ||
1294 | |||
1295 | buf = alloca(salt_len + 4); | ||
1296 | if (!buf) | ||
1297 | return 1; | ||
1298 | |||
1299 | for (i = 1; len; len -= tmp_len, p += tmp_len, i++) | ||
1300 | { | ||
1301 | if (len > digest_len) | ||
1302 | tmp_len = digest_len; | ||
1303 | else | ||
1304 | tmp_len = len; | ||
1305 | |||
1306 | tab[0] = (unsigned char)(i & 0xff000000) >> 24; | ||
1307 | tab[1] = (unsigned char)(i & 0x00ff0000) >> 16; | ||
1308 | tab[2] = (unsigned char)(i & 0x0000ff00) >> 8; | ||
1309 | tab[3] = (unsigned char)(i & 0x000000ff) >> 0; | ||
1310 | |||
1311 | # ifdef HAVE_GNUTLS | ||
1312 | memcpy(buf, salt, salt_len); | ||
1313 | memcpy(buf + salt_len, tab, 4); | ||
1314 | eet_hmac_sha1(key, key_len, buf, salt_len + 4, digest); | ||
1315 | # else /* ifdef HAVE_GNUTLS */ | ||
1316 | HMAC_Init(&hctx, key, key_len, EVP_sha1()); | ||
1317 | HMAC_Update(&hctx, salt, salt_len); | ||
1318 | HMAC_Update(&hctx, tab, 4); | ||
1319 | HMAC_Final(&hctx, digest, NULL); | ||
1320 | # endif /* ifdef HAVE_GNUTLS */ | ||
1321 | memcpy(p, digest, tmp_len); | ||
1322 | |||
1323 | for (j = 1; j < iter; j++) | ||
1324 | { | ||
1325 | # ifdef HAVE_GNUTLS | ||
1326 | eet_hmac_sha1(key, key_len, digest, 20, digest); | ||
1327 | # else /* ifdef HAVE_GNUTLS */ | ||
1328 | HMAC(EVP_sha1(), key, key_len, digest, 20, digest, NULL); | ||
1329 | # endif /* ifdef HAVE_GNUTLS */ | ||
1330 | for (k = 0; k < tmp_len; k++) | ||
1331 | p[k] ^= digest[k]; | ||
1332 | } | ||
1333 | } | ||
1334 | |||
1335 | # ifdef HAVE_GNUTLS | ||
1336 | # else | ||
1337 | HMAC_cleanup(&hctx); | ||
1338 | # endif /* ifdef HAVE_GNUTLS */ | ||
1339 | return 0; | ||
1340 | } /* eet_pbkdf2_sha1 */ | ||
1341 | |||
1342 | #endif /* ifdef HAVE_CIPHER */ | ||
diff --git a/libraries/eet/src/lib/eet_connection.c b/libraries/eet/src/lib/eet_connection.c new file mode 100644 index 0000000..6171b7e --- /dev/null +++ b/libraries/eet/src/lib/eet_connection.c | |||
@@ -0,0 +1,249 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif /* ifdef HAVE_CONFIG_H */ | ||
4 | |||
5 | #ifdef HAVE_ALLOCA_H | ||
6 | # include <alloca.h> | ||
7 | #elif defined __GNUC__ | ||
8 | # define alloca __builtin_alloca | ||
9 | #elif defined _AIX | ||
10 | # define alloca __alloca | ||
11 | #elif defined _MSC_VER | ||
12 | # include <malloc.h> | ||
13 | # define alloca _alloca | ||
14 | #else /* ifdef HAVE_ALLOCA_H */ | ||
15 | # include <stddef.h> | ||
16 | # ifdef __cplusplus | ||
17 | extern "C" | ||
18 | # endif /* ifdef __cplusplus */ | ||
19 | void *alloca(size_t); | ||
20 | #endif /* ifdef HAVE_ALLOCA_H */ | ||
21 | |||
22 | #include <string.h> | ||
23 | #include <stdlib.h> | ||
24 | |||
25 | #ifdef HAVE_NETINET_IN_H | ||
26 | # include <netinet/in.h> | ||
27 | #endif /* ifdef HAVE_NETINET_IN_H */ | ||
28 | |||
29 | #ifdef _WIN32 | ||
30 | # include <winsock2.h> | ||
31 | #endif /* ifdef _WIN32 */ | ||
32 | |||
33 | #include <Eina.h> | ||
34 | |||
35 | #include "Eet.h" | ||
36 | #include "Eet_private.h" | ||
37 | |||
38 | #define MAGIC_EET_DATA_PACKET 0x4270ACE1 | ||
39 | |||
40 | struct _Eet_Connection | ||
41 | { | ||
42 | Eet_Read_Cb *eet_read_cb; | ||
43 | Eet_Write_Cb *eet_write_cb; | ||
44 | void *user_data; | ||
45 | |||
46 | size_t allocated; | ||
47 | size_t size; | ||
48 | size_t received; | ||
49 | |||
50 | void *buffer; | ||
51 | }; | ||
52 | |||
53 | EAPI Eet_Connection * | ||
54 | eet_connection_new(Eet_Read_Cb *eet_read_cb, | ||
55 | Eet_Write_Cb *eet_write_cb, | ||
56 | const void *user_data) | ||
57 | { | ||
58 | Eet_Connection *conn; | ||
59 | |||
60 | if (!eet_read_cb || !eet_write_cb) | ||
61 | return NULL; | ||
62 | |||
63 | conn = calloc(1, sizeof (Eet_Connection)); | ||
64 | if (!conn) | ||
65 | return NULL; | ||
66 | |||
67 | conn->eet_read_cb = eet_read_cb; | ||
68 | conn->eet_write_cb = eet_write_cb; | ||
69 | conn->user_data = (void *)user_data; | ||
70 | |||
71 | return conn; | ||
72 | } /* eet_connection_new */ | ||
73 | |||
74 | EAPI int | ||
75 | eet_connection_received(Eet_Connection *conn, | ||
76 | const void *data, | ||
77 | size_t size) | ||
78 | { | ||
79 | if ((!conn) || (!data) || (!size)) | ||
80 | return size; | ||
81 | |||
82 | do { | ||
83 | size_t copy_size; | ||
84 | |||
85 | if (conn->size == 0) | ||
86 | { | ||
87 | const int *msg; | ||
88 | size_t packet_size; | ||
89 | |||
90 | if (size < sizeof (int) * 2) | ||
91 | break; | ||
92 | |||
93 | msg = data; | ||
94 | /* Check the magic */ | ||
95 | if (ntohl(msg[0]) != MAGIC_EET_DATA_PACKET) | ||
96 | break; | ||
97 | |||
98 | packet_size = ntohl(msg[1]); | ||
99 | /* Message should always be under 64K */ | ||
100 | if (packet_size > 64 * 1024) | ||
101 | break; | ||
102 | |||
103 | data = (void *)(msg + 2); | ||
104 | size -= sizeof (int) * 2; | ||
105 | if ((size_t)packet_size <= size) | ||
106 | { | ||
107 | /* Not a partial receive, go the quick way. */ | ||
108 | if (!conn->eet_read_cb(data, packet_size, conn->user_data)) | ||
109 | break; | ||
110 | |||
111 | data = (void *)((char *)data + packet_size); | ||
112 | size -= packet_size; | ||
113 | |||
114 | conn->received = 0; | ||
115 | continue; | ||
116 | } | ||
117 | |||
118 | conn->size = packet_size; | ||
119 | if (conn->allocated < conn->size) | ||
120 | { | ||
121 | void *tmp; | ||
122 | |||
123 | tmp = realloc(conn->buffer, conn->size); | ||
124 | if (!tmp) | ||
125 | break; | ||
126 | |||
127 | conn->buffer = tmp; | ||
128 | conn->allocated = conn->size; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | /* Partial receive */ | ||
133 | copy_size = | ||
134 | (conn->size - conn->received >= | ||
135 | size) ? size : conn->size - conn->received; | ||
136 | memcpy((char *)conn->buffer + conn->received, data, copy_size); | ||
137 | |||
138 | conn->received += copy_size; | ||
139 | data = (void *)((char *)data + copy_size); | ||
140 | size -= copy_size; | ||
141 | |||
142 | if (conn->received == conn->size) | ||
143 | { | ||
144 | size_t data_size; | ||
145 | |||
146 | data_size = conn->size; | ||
147 | conn->size = 0; | ||
148 | conn->received = 0; | ||
149 | |||
150 | /* Completed a packet. */ | ||
151 | if (!conn->eet_read_cb(conn->buffer, data_size, conn->user_data)) | ||
152 | { | ||
153 | /* Something goes wrong. Stop now. */ | ||
154 | size += data_size; | ||
155 | break; | ||
156 | } | ||
157 | } | ||
158 | } while (size > 0); | ||
159 | |||
160 | return size; | ||
161 | } /* eet_connection_received */ | ||
162 | |||
163 | static Eina_Bool | ||
164 | _eet_connection_raw_send(Eet_Connection *conn, | ||
165 | void *data, | ||
166 | int data_size) | ||
167 | { | ||
168 | int *message; | ||
169 | |||
170 | /* Message should never be above 64K */ | ||
171 | if (data_size > 64 * 1024) | ||
172 | return EINA_FALSE; | ||
173 | |||
174 | message = alloca(data_size + sizeof (int) * 2); | ||
175 | message[0] = htonl(MAGIC_EET_DATA_PACKET); | ||
176 | message[1] = htonl(data_size); | ||
177 | |||
178 | memcpy(message + 2, data, data_size); | ||
179 | |||
180 | conn->eet_write_cb(message, | ||
181 | data_size + sizeof (int) * 2, | ||
182 | conn->user_data); | ||
183 | return EINA_TRUE; | ||
184 | } /* _eet_connection_raw_send */ | ||
185 | |||
186 | EAPI Eina_Bool | ||
187 | eet_connection_send(Eet_Connection *conn, | ||
188 | Eet_Data_Descriptor *edd, | ||
189 | const void *data_in, | ||
190 | const char *cipher_key) | ||
191 | { | ||
192 | void *flat_data; | ||
193 | int data_size; | ||
194 | Eina_Bool ret = EINA_FALSE; | ||
195 | |||
196 | flat_data = eet_data_descriptor_encode_cipher(edd, | ||
197 | data_in, | ||
198 | cipher_key, | ||
199 | &data_size); | ||
200 | if (!flat_data) | ||
201 | return EINA_FALSE; | ||
202 | |||
203 | if (_eet_connection_raw_send(conn, flat_data, data_size)) | ||
204 | ret = EINA_TRUE; | ||
205 | |||
206 | free(flat_data); | ||
207 | return ret; | ||
208 | } /* eet_connection_send */ | ||
209 | |||
210 | EAPI Eina_Bool | ||
211 | eet_connection_node_send(Eet_Connection *conn, | ||
212 | Eet_Node *node, | ||
213 | const char *cipher_key) | ||
214 | { | ||
215 | void *data; | ||
216 | int data_size; | ||
217 | Eina_Bool ret = EINA_FALSE; | ||
218 | |||
219 | data = eet_data_node_encode_cipher(node, cipher_key, &data_size); | ||
220 | if (!data) | ||
221 | return EINA_FALSE; | ||
222 | |||
223 | if (_eet_connection_raw_send(conn, data, data_size)) | ||
224 | ret = EINA_TRUE; | ||
225 | |||
226 | free(data); | ||
227 | return ret; | ||
228 | } /* eet_connection_node_send */ | ||
229 | |||
230 | EAPI void * | ||
231 | eet_connection_close(Eet_Connection *conn, | ||
232 | Eina_Bool *on_going) | ||
233 | { | ||
234 | void *user_data; | ||
235 | |||
236 | if (!conn) | ||
237 | return NULL; | ||
238 | |||
239 | if (on_going) | ||
240 | *on_going = conn->received == 0 ? EINA_FALSE : EINA_TRUE; | ||
241 | |||
242 | user_data = conn->user_data; | ||
243 | |||
244 | free(conn->buffer); | ||
245 | free(conn); | ||
246 | |||
247 | return user_data; | ||
248 | } /* eet_connection_close */ | ||
249 | |||
diff --git a/libraries/eet/src/lib/eet_data.c b/libraries/eet/src/lib/eet_data.c new file mode 100644 index 0000000..23b0b97 --- /dev/null +++ b/libraries/eet/src/lib/eet_data.c | |||
@@ -0,0 +1,4999 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif /* ifdef HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <stdio.h> | ||
6 | #include <string.h> | ||
7 | #include <math.h> | ||
8 | #include <ctype.h> | ||
9 | #include <limits.h> | ||
10 | |||
11 | #ifdef HAVE_NETINET_IN_H | ||
12 | # include <netinet/in.h> | ||
13 | #endif /* ifdef HAVE_NETINET_IN_H */ | ||
14 | |||
15 | #ifdef _WIN32 | ||
16 | # include <winsock2.h> | ||
17 | #endif /* ifdef _WIN32 */ | ||
18 | |||
19 | #include <Eina.h> | ||
20 | |||
21 | #include "Eet.h" | ||
22 | #include "Eet_private.h" | ||
23 | |||
24 | #ifdef _WIN32 | ||
25 | # define FMT_CHAR "%c" | ||
26 | # define FMT_UCHAR "%c" | ||
27 | # define FMT_LONG_LONG "%I64i" | ||
28 | # define FMT_ULONG_LONG "%I64u" | ||
29 | #else | ||
30 | # define FMT_CHAR "%hhi" | ||
31 | # define FMT_UCHAR "%hhu" | ||
32 | # define FMT_LONG_LONG "%lli" | ||
33 | # define FMT_ULONG_LONG "%llu" | ||
34 | #endif | ||
35 | |||
36 | /* | ||
37 | * routines for doing data -> struct and struct -> data conversion | ||
38 | * | ||
39 | * types: | ||
40 | * | ||
41 | * basic types: | ||
42 | * a sequence of... | ||
43 | * | ||
44 | * char | ||
45 | * short | ||
46 | * int | ||
47 | * long long | ||
48 | * float | ||
49 | * double | ||
50 | * unsigned char | ||
51 | * unsigned short | ||
52 | * unsigned int | ||
53 | * unsgined long long | ||
54 | * string | ||
55 | * | ||
56 | * groupings: | ||
57 | * multiple entries ordered as... | ||
58 | * | ||
59 | * fixed size array [ of basic types ] | ||
60 | * variable size array [ of basic types ] | ||
61 | * linked list [ of basic types ] | ||
62 | * hash table [ of basic types ] | ||
63 | * | ||
64 | * need to provide builder/accessor funcs for: | ||
65 | * | ||
66 | * list_next | ||
67 | * list_append | ||
68 | * | ||
69 | * hash_foreach | ||
70 | * hash_add | ||
71 | * | ||
72 | */ | ||
73 | |||
74 | /*---*/ | ||
75 | |||
76 | typedef struct _Eet_Data_Element Eet_Data_Element; | ||
77 | typedef struct _Eet_Data_Basic_Type_Codec Eet_Data_Basic_Type_Codec; | ||
78 | typedef struct _Eet_Data_Group_Type_Codec Eet_Data_Group_Type_Codec; | ||
79 | typedef struct _Eet_Data_Chunk Eet_Data_Chunk; | ||
80 | typedef struct _Eet_Data_Stream Eet_Data_Stream; | ||
81 | typedef struct _Eet_Data_Descriptor_Hash Eet_Data_Descriptor_Hash; | ||
82 | typedef struct _Eet_Data_Encode_Hash_Info Eet_Data_Encode_Hash_Info; | ||
83 | typedef struct _Eet_Free Eet_Free; | ||
84 | typedef struct _Eet_Free_Context Eet_Free_Context; | ||
85 | typedef struct _Eet_Variant_Unknow Eet_Variant_Unknow; | ||
86 | |||
87 | /*---*/ | ||
88 | |||
89 | /* TODO: | ||
90 | * Eet_Data_Basic_Type_Codec (Coder, Decoder) | ||
91 | * Eet_Data_Group_Type_Codec (Coder, Decoder) | ||
92 | */ | ||
93 | struct _Eet_Data_Basic_Type_Codec | ||
94 | { | ||
95 | int size; | ||
96 | const char *name; | ||
97 | int (*get)(const Eet_Dictionary *ed, | ||
98 | const void *src, | ||
99 | const void *src_end, | ||
100 | void *dest); | ||
101 | void * (*put)(Eet_Dictionary *ed, const void *src, int *size_ret); | ||
102 | }; | ||
103 | |||
104 | struct _Eet_Data_Group_Type_Codec | ||
105 | { | ||
106 | int (*get)(Eet_Free_Context *context, | ||
107 | const Eet_Dictionary *ed, | ||
108 | Eet_Data_Descriptor *edd, | ||
109 | Eet_Data_Element *ede, | ||
110 | Eet_Data_Chunk *echnk, | ||
111 | int type, | ||
112 | int group_type, | ||
113 | void *data_in, | ||
114 | char **p, | ||
115 | int *size); | ||
116 | void (*put)(Eet_Dictionary *ed, | ||
117 | Eet_Data_Descriptor *edd, | ||
118 | Eet_Data_Element *ede, | ||
119 | Eet_Data_Stream *ds, | ||
120 | void *data_in); | ||
121 | }; | ||
122 | |||
123 | struct _Eet_Data_Chunk | ||
124 | { | ||
125 | char *name; | ||
126 | int len; | ||
127 | int size; | ||
128 | int hash; | ||
129 | void *data; | ||
130 | unsigned char type; | ||
131 | unsigned char group_type; | ||
132 | }; | ||
133 | |||
134 | struct _Eet_Data_Stream | ||
135 | { | ||
136 | void *data; | ||
137 | int size; | ||
138 | int pos; | ||
139 | }; | ||
140 | |||
141 | struct _Eet_Data_Descriptor_Hash | ||
142 | { | ||
143 | Eet_Data_Element *element; | ||
144 | Eet_Data_Descriptor_Hash *next; | ||
145 | }; | ||
146 | |||
147 | struct _Eet_Data_Descriptor | ||
148 | { | ||
149 | const char *name; | ||
150 | const Eet_Dictionary *ed; | ||
151 | int size; | ||
152 | struct | ||
153 | { | ||
154 | void * (*mem_alloc)(size_t size); | ||
155 | void (*mem_free)(void *mem); | ||
156 | char * (*str_alloc)(const char *str); | ||
157 | char * (*str_direct_alloc)(const char *str); | ||
158 | void (*str_free)(const char *str); | ||
159 | void (*str_direct_free)(const char *str); | ||
160 | void * (*list_next)(void *l); | ||
161 | void * (*list_append)(void *l, void *d); | ||
162 | void * (*list_data)(void *l); | ||
163 | void * (*list_free)(void *l); | ||
164 | void (*hash_foreach)(void *h, | ||
165 | int (*func)(void *h, | ||
166 | const char *k, | ||
167 | void *dt, | ||
168 | void *fdt), | ||
169 | void *fdt); | ||
170 | void * (*hash_add)(void *h, const char *k, void *d); | ||
171 | void (*hash_free)(void *h); | ||
172 | const char *(*type_get)(const void *data, Eina_Bool *unknow); | ||
173 | Eina_Bool (*type_set)(const char *type, | ||
174 | void *data, | ||
175 | Eina_Bool unknow); | ||
176 | void * (*array_alloc)(size_t size); | ||
177 | void (*array_free)(void *mem); | ||
178 | } func; | ||
179 | struct | ||
180 | { | ||
181 | int num; | ||
182 | Eet_Data_Element *set; | ||
183 | struct | ||
184 | { | ||
185 | int size; | ||
186 | Eet_Data_Descriptor_Hash *buckets; | ||
187 | } hash; | ||
188 | } elements; | ||
189 | |||
190 | Eina_Bool unified_type : 1; | ||
191 | // char *strings; | ||
192 | // int strings_len; | ||
193 | }; | ||
194 | |||
195 | struct _Eet_Data_Element | ||
196 | { | ||
197 | const char *name; | ||
198 | const char *counter_name; | ||
199 | const char *directory_name_ptr; | ||
200 | Eet_Data_Descriptor *subtype; | ||
201 | int offset; /* offset in bytes from the base element */ | ||
202 | int count; /* number of elements for a fixed array */ | ||
203 | int counter_offset; /* for a variable array we need the offset of the count variable */ | ||
204 | unsigned char type; /* EET_T_XXX */ | ||
205 | unsigned char group_type; /* EET_G_XXX */ | ||
206 | }; | ||
207 | |||
208 | struct _Eet_Data_Encode_Hash_Info | ||
209 | { | ||
210 | Eet_Data_Stream *ds; | ||
211 | Eet_Data_Element *ede; | ||
212 | Eet_Dictionary *ed; | ||
213 | }; | ||
214 | |||
215 | #define EET_FREE_COUNT 256 | ||
216 | struct _Eet_Free | ||
217 | { | ||
218 | int ref; | ||
219 | Eina_Array list[EET_FREE_COUNT]; | ||
220 | }; | ||
221 | |||
222 | struct _Eet_Free_Context | ||
223 | { | ||
224 | Eet_Free freelist; | ||
225 | Eet_Free freelist_array; | ||
226 | Eet_Free freelist_list; | ||
227 | Eet_Free freelist_hash; | ||
228 | Eet_Free freelist_str; | ||
229 | Eet_Free freelist_direct_str; | ||
230 | }; | ||
231 | |||
232 | struct _Eet_Variant_Unknow | ||
233 | { | ||
234 | EINA_MAGIC | ||
235 | |||
236 | int size; | ||
237 | char data[1]; | ||
238 | }; | ||
239 | |||
240 | /*---*/ | ||
241 | |||
242 | static void | ||
243 | eet_free_context_init(Eet_Free_Context *context); | ||
244 | static void | ||
245 | eet_free_context_shutdown(Eet_Free_Context *context); | ||
246 | |||
247 | static int | ||
248 | eet_data_get_char(const Eet_Dictionary *ed, | ||
249 | const void *src, | ||
250 | const void *src_end, | ||
251 | void *dest); | ||
252 | static void * | ||
253 | eet_data_put_char(Eet_Dictionary *ed, | ||
254 | const void *src, | ||
255 | int *size_ret); | ||
256 | static int | ||
257 | eet_data_get_short(const Eet_Dictionary *ed, | ||
258 | const void *src, | ||
259 | const void *src_end, | ||
260 | void *dest); | ||
261 | static void * | ||
262 | eet_data_put_short(Eet_Dictionary *ed, | ||
263 | const void *src, | ||
264 | int *size_ret); | ||
265 | static inline int | ||
266 | eet_data_get_int(const Eet_Dictionary *ed, | ||
267 | const void *src, | ||
268 | const void *src_end, | ||
269 | void *dest); | ||
270 | static void * | ||
271 | eet_data_put_int(Eet_Dictionary *ed, | ||
272 | const void *src, | ||
273 | int *size_ret); | ||
274 | static int | ||
275 | eet_data_get_long_long(const Eet_Dictionary *ed, | ||
276 | const void *src, | ||
277 | const void *src_end, | ||
278 | void *dest); | ||
279 | static void * | ||
280 | eet_data_put_long_long(Eet_Dictionary *ed, | ||
281 | const void *src, | ||
282 | int *size_ret); | ||
283 | static int | ||
284 | eet_data_get_float(const Eet_Dictionary *ed, | ||
285 | const void *src, | ||
286 | const void *src_end, | ||
287 | void *dest); | ||
288 | static void * | ||
289 | eet_data_put_float(Eet_Dictionary *ed, | ||
290 | const void *src, | ||
291 | int *size_ret); | ||
292 | static int | ||
293 | eet_data_get_double(const Eet_Dictionary *ed, | ||
294 | const void *src, | ||
295 | const void *src_end, | ||
296 | void *dest); | ||
297 | static void * | ||
298 | eet_data_put_double(Eet_Dictionary *ed, | ||
299 | const void *src, | ||
300 | int *size_ret); | ||
301 | static int | ||
302 | eet_data_get_f32p32(const Eet_Dictionary *ed, | ||
303 | const void *src, | ||
304 | const void *src_end, | ||
305 | void *dest); | ||
306 | static void * | ||
307 | eet_data_put_f32p32(Eet_Dictionary *ed, | ||
308 | const void *src, | ||
309 | int *size_ret); | ||
310 | static int | ||
311 | eet_data_get_f16p16(const Eet_Dictionary *ed, | ||
312 | const void *src, | ||
313 | const void *src_end, | ||
314 | void *dest); | ||
315 | static void * | ||
316 | eet_data_put_f16p16(Eet_Dictionary *ed, | ||
317 | const void *src, | ||
318 | int *size_ret); | ||
319 | static int | ||
320 | eet_data_get_f8p24(const Eet_Dictionary *ed, | ||
321 | const void *src, | ||
322 | const void *src_end, | ||
323 | void *dest); | ||
324 | static void * | ||
325 | eet_data_put_f8p24(Eet_Dictionary *ed, | ||
326 | const void *src, | ||
327 | int *size_ret); | ||
328 | static inline int | ||
329 | eet_data_get_string(const Eet_Dictionary *ed, | ||
330 | const void *src, | ||
331 | const void *src_end, | ||
332 | void *dest); | ||
333 | static void * | ||
334 | eet_data_put_string(Eet_Dictionary *ed, | ||
335 | const void *src, | ||
336 | int *size_ret); | ||
337 | static int | ||
338 | eet_data_get_istring(const Eet_Dictionary *ed, | ||
339 | const void *src, | ||
340 | const void *src_end, | ||
341 | void *dest); | ||
342 | static void * | ||
343 | eet_data_put_istring(Eet_Dictionary *ed, | ||
344 | const void *src, | ||
345 | int *size_ret); | ||
346 | static int | ||
347 | eet_data_get_null(const Eet_Dictionary *ed, | ||
348 | const void *src, | ||
349 | const void *src_end, | ||
350 | void *dest); | ||
351 | static void * | ||
352 | eet_data_put_null(Eet_Dictionary *ed, | ||
353 | const void *src, | ||
354 | int *size_ret); | ||
355 | |||
356 | static int | ||
357 | eet_data_get_type(const Eet_Dictionary *ed, | ||
358 | int type, | ||
359 | const void *src, | ||
360 | const void *src_end, | ||
361 | void *dest); | ||
362 | static void * | ||
363 | eet_data_put_type(Eet_Dictionary *ed, | ||
364 | int type, | ||
365 | const void *src, | ||
366 | int *size_ret); | ||
367 | |||
368 | static Eet_Node * | ||
369 | eet_data_node_simple_type(int type, | ||
370 | const char *name, | ||
371 | void *dd); | ||
372 | |||
373 | static int | ||
374 | eet_data_get_unknown(Eet_Free_Context *context, | ||
375 | const Eet_Dictionary *ed, | ||
376 | Eet_Data_Descriptor *edd, | ||
377 | Eet_Data_Element *ede, | ||
378 | Eet_Data_Chunk *echnk, | ||
379 | int type, | ||
380 | int group_type, | ||
381 | void *data_in, | ||
382 | char **p, | ||
383 | int *size); | ||
384 | static void | ||
385 | eet_data_put_unknown(Eet_Dictionary *ed, | ||
386 | Eet_Data_Descriptor *edd, | ||
387 | Eet_Data_Element *ede, | ||
388 | Eet_Data_Stream *ds, | ||
389 | void *data_in); | ||
390 | static void | ||
391 | eet_data_put_array(Eet_Dictionary *ed, | ||
392 | Eet_Data_Descriptor *edd, | ||
393 | Eet_Data_Element *ede, | ||
394 | Eet_Data_Stream *ds, | ||
395 | void *data_in); | ||
396 | static int | ||
397 | eet_data_get_array(Eet_Free_Context *context, | ||
398 | const Eet_Dictionary *ed, | ||
399 | Eet_Data_Descriptor *edd, | ||
400 | Eet_Data_Element *ede, | ||
401 | Eet_Data_Chunk *echnk, | ||
402 | int type, | ||
403 | int group_type, | ||
404 | void *data, | ||
405 | char **p, | ||
406 | int *size); | ||
407 | static int | ||
408 | eet_data_get_list(Eet_Free_Context *context, | ||
409 | const Eet_Dictionary *ed, | ||
410 | Eet_Data_Descriptor *edd, | ||
411 | Eet_Data_Element *ede, | ||
412 | Eet_Data_Chunk *echnk, | ||
413 | int type, | ||
414 | int group_type, | ||
415 | void *data_in, | ||
416 | char **p, | ||
417 | int *size); | ||
418 | static void | ||
419 | eet_data_put_list(Eet_Dictionary *ed, | ||
420 | Eet_Data_Descriptor *edd, | ||
421 | Eet_Data_Element *ede, | ||
422 | Eet_Data_Stream *ds, | ||
423 | void *data_in); | ||
424 | static void | ||
425 | eet_data_put_hash(Eet_Dictionary *ed, | ||
426 | Eet_Data_Descriptor *edd, | ||
427 | Eet_Data_Element *ede, | ||
428 | Eet_Data_Stream *ds, | ||
429 | void *data_in); | ||
430 | static int | ||
431 | eet_data_get_hash(Eet_Free_Context *context, | ||
432 | const Eet_Dictionary *ed, | ||
433 | Eet_Data_Descriptor *edd, | ||
434 | Eet_Data_Element *ede, | ||
435 | Eet_Data_Chunk *echnk, | ||
436 | int type, | ||
437 | int group_type, | ||
438 | void *data, | ||
439 | char **p, | ||
440 | int *size); | ||
441 | static void | ||
442 | eet_data_put_union(Eet_Dictionary *ed, | ||
443 | Eet_Data_Descriptor *edd, | ||
444 | Eet_Data_Element *ede, | ||
445 | Eet_Data_Stream *ds, | ||
446 | void *data_in); | ||
447 | static int | ||
448 | eet_data_get_union(Eet_Free_Context *context, | ||
449 | const Eet_Dictionary *ed, | ||
450 | Eet_Data_Descriptor *edd, | ||
451 | Eet_Data_Element *ede, | ||
452 | Eet_Data_Chunk *echnk, | ||
453 | int type, | ||
454 | int group_type, | ||
455 | void *data, | ||
456 | char **p, | ||
457 | int *size); | ||
458 | static void | ||
459 | eet_data_put_variant(Eet_Dictionary *ed, | ||
460 | Eet_Data_Descriptor *edd, | ||
461 | Eet_Data_Element *ede, | ||
462 | Eet_Data_Stream *ds, | ||
463 | void *data_in); | ||
464 | static int | ||
465 | eet_data_get_variant(Eet_Free_Context *context, | ||
466 | const Eet_Dictionary *ed, | ||
467 | Eet_Data_Descriptor *edd, | ||
468 | Eet_Data_Element *ede, | ||
469 | Eet_Data_Chunk *echnk, | ||
470 | int type, | ||
471 | int group_type, | ||
472 | void *data, | ||
473 | char **p, | ||
474 | int *size); | ||
475 | |||
476 | static void | ||
477 | eet_data_chunk_get(const Eet_Dictionary *ed, | ||
478 | Eet_Data_Chunk *chnk, | ||
479 | const void *src, | ||
480 | int size); | ||
481 | static Eet_Data_Chunk * | ||
482 | eet_data_chunk_new(void *data, | ||
483 | int size, | ||
484 | const char *name, | ||
485 | int type, | ||
486 | int group_type); | ||
487 | static void | ||
488 | eet_data_chunk_free(Eet_Data_Chunk *chnk); | ||
489 | |||
490 | static Eet_Data_Stream * | ||
491 | eet_data_stream_new(void); | ||
492 | static void | ||
493 | eet_data_stream_write(Eet_Data_Stream *ds, | ||
494 | const void *data, | ||
495 | int size); | ||
496 | static void | ||
497 | eet_data_stream_free(Eet_Data_Stream *ds); | ||
498 | |||
499 | static void | ||
500 | eet_data_chunk_put(Eet_Dictionary *ed, | ||
501 | Eet_Data_Chunk *chnk, | ||
502 | Eet_Data_Stream *ds); | ||
503 | |||
504 | static int | ||
505 | eet_data_descriptor_encode_hash_cb(void *hash, | ||
506 | const char *key, | ||
507 | void *hdata, | ||
508 | void *fdata); | ||
509 | static void *_eet_data_descriptor_encode(Eet_Dictionary *ed, | ||
510 | Eet_Data_Descriptor *edd, | ||
511 | const void *data_in, | ||
512 | int *size_ret); | ||
513 | static void *_eet_data_descriptor_decode(Eet_Free_Context *context, | ||
514 | const Eet_Dictionary *ed, | ||
515 | Eet_Data_Descriptor *edd, | ||
516 | const void *data_in, | ||
517 | int size_in, | ||
518 | void *data_out, | ||
519 | int size_out); | ||
520 | |||
521 | /*---*/ | ||
522 | |||
523 | static const Eet_Data_Basic_Type_Codec eet_basic_codec[] = | ||
524 | { | ||
525 | {sizeof(char), "char", eet_data_get_char, eet_data_put_char }, | ||
526 | {sizeof(short), "short", eet_data_get_short, eet_data_put_short }, | ||
527 | {sizeof(int), "int", eet_data_get_int, eet_data_put_int }, | ||
528 | {sizeof(long long), "long_long", eet_data_get_long_long, eet_data_put_long_long}, | ||
529 | {sizeof(float), "float", eet_data_get_float, eet_data_put_float }, | ||
530 | {sizeof(double), "double", eet_data_get_double, eet_data_put_double }, | ||
531 | {sizeof(char), "uchar", eet_data_get_char, eet_data_put_char }, | ||
532 | {sizeof(short), "ushort", eet_data_get_short, eet_data_put_short }, | ||
533 | {sizeof(int), "uint", eet_data_get_int, eet_data_put_int }, | ||
534 | {sizeof(long long), "ulong_long", eet_data_get_long_long, eet_data_put_long_long}, | ||
535 | {sizeof(char *), "string", eet_data_get_string, eet_data_put_string }, | ||
536 | {sizeof(char *), "inlined", eet_data_get_istring, eet_data_put_istring }, | ||
537 | {sizeof(void *), "NULL", eet_data_get_null, eet_data_put_null }, | ||
538 | {sizeof(Eina_F32p32), "f32p32", eet_data_get_f32p32, eet_data_put_f32p32 }, | ||
539 | {sizeof(Eina_F16p16), "f16p16", eet_data_get_f16p16, eet_data_put_f16p16 }, | ||
540 | {sizeof(Eina_F8p24), "f8p24", eet_data_get_f8p24, eet_data_put_f8p24 } | ||
541 | }; | ||
542 | |||
543 | static const Eet_Data_Group_Type_Codec eet_group_codec[] = | ||
544 | { | ||
545 | { eet_data_get_unknown, eet_data_put_unknown }, | ||
546 | { eet_data_get_array, eet_data_put_array }, | ||
547 | { eet_data_get_array, eet_data_put_array }, | ||
548 | { eet_data_get_list, eet_data_put_list }, | ||
549 | { eet_data_get_hash, eet_data_put_hash }, | ||
550 | { eet_data_get_union, eet_data_put_union }, | ||
551 | { eet_data_get_variant, eet_data_put_variant } | ||
552 | }; | ||
553 | |||
554 | static int _eet_data_words_bigendian = -1; | ||
555 | |||
556 | /*---*/ | ||
557 | |||
558 | #define SWAP64(x) (x) = \ | ||
559 | ((((unsigned long long)(x) & 0x00000000000000ffULL) << 56) | \ | ||
560 | (((unsigned long long)(x) & 0x000000000000ff00ULL) << 40) | \ | ||
561 | (((unsigned long long)(x) & 0x0000000000ff0000ULL) << 24) | \ | ||
562 | (((unsigned long long)(x) & 0x00000000ff000000ULL) << 8) | \ | ||
563 | (((unsigned long long)(x) & 0x000000ff00000000ULL) >> 8) | \ | ||
564 | (((unsigned long long)(x) & 0x0000ff0000000000ULL) >> 24) | \ | ||
565 | (((unsigned long long)(x) & 0x00ff000000000000ULL) >> 40) | \ | ||
566 | (((unsigned long long)(x) & 0xff00000000000000ULL) >> 56)) | ||
567 | #define SWAP32(x) (x) = \ | ||
568 | ((((int)(x) & 0x000000ff) << 24) | \ | ||
569 | (((int)(x) & 0x0000ff00) << 8) | \ | ||
570 | (((int)(x) & 0x00ff0000) >> 8) | \ | ||
571 | (((int)(x) & 0xff000000) >> 24)) | ||
572 | #define SWAP16(x) (x) = \ | ||
573 | ((((short)(x) & 0x00ff) << 8) | \ | ||
574 | (((short)(x) & 0xff00) >> 8)) | ||
575 | |||
576 | #ifdef CONV8 | ||
577 | # undef CONV8 | ||
578 | #endif /* ifdef CONV8 */ | ||
579 | #ifdef CONV16 | ||
580 | # undef CONV16 | ||
581 | #endif /* ifdef CONV16 */ | ||
582 | #ifdef CONV32 | ||
583 | # undef CONV32 | ||
584 | #endif /* ifdef CONV32 */ | ||
585 | #ifdef CONV64 | ||
586 | # undef CONV64 | ||
587 | #endif /* ifdef CONV64 */ | ||
588 | |||
589 | #define CONV8(x) | ||
590 | #define CONV16(x) {if (_eet_data_words_bigendian) {SWAP16(x); }} | ||
591 | #define CONV32(x) {if (_eet_data_words_bigendian) {SWAP32(x); }} | ||
592 | #define CONV64(x) {if (_eet_data_words_bigendian) {SWAP64(x); }} | ||
593 | |||
594 | #define IS_SIMPLE_TYPE(Type) (Type > EET_T_UNKNOW && Type < EET_T_LAST) | ||
595 | #define IS_POINTER_TYPE(Type) (Type >= EET_T_STRING && Type <= EET_T_NULL) | ||
596 | |||
597 | #define POINTER_TYPE_DECODE(Context, \ | ||
598 | Ed, \ | ||
599 | Edd, \ | ||
600 | Ede, \ | ||
601 | Echnk, \ | ||
602 | Type, \ | ||
603 | Data, \ | ||
604 | P, \ | ||
605 | Size, \ | ||
606 | Label) \ | ||
607 | do { \ | ||
608 | int ___r; \ | ||
609 | ___r = eet_data_get_unknown(Context, \ | ||
610 | Ed, \ | ||
611 | Edd, Ede, \ | ||
612 | Echnk, \ | ||
613 | Type, EET_G_UNKNOWN, \ | ||
614 | Data, P, Size); \ | ||
615 | if (!___r) { goto Label; } \ | ||
616 | } while (0) | ||
617 | |||
618 | #define STRUCT_TYPE_DECODE(Data_Ret, Context, Ed, Ede, Data, Size, SubSize, Label) \ | ||
619 | do { \ | ||
620 | Data_Ret = _eet_data_descriptor_decode(Context, \ | ||
621 | Ed, \ | ||
622 | Ede, \ | ||
623 | Data, \ | ||
624 | Size, \ | ||
625 | SubSize > 0 ? Data_Ret : NULL, \ | ||
626 | SubSize); \ | ||
627 | if (!Data_Ret) { goto Label; } \ | ||
628 | } while (0) | ||
629 | |||
630 | #define EET_I_STRING 1 << 4 | ||
631 | #define EET_I_INLINED_STRING 2 << 4 | ||
632 | #define EET_I_NULL 3 << 4 | ||
633 | |||
634 | #define EET_MAGIC_VARIANT 0xF1234BC | ||
635 | /*---*/ | ||
636 | |||
637 | /* CHAR TYPE */ | ||
638 | static int | ||
639 | eet_data_get_char(const Eet_Dictionary *ed __UNUSED__, | ||
640 | const void *src, | ||
641 | const void *src_end, | ||
642 | void *dst) | ||
643 | { | ||
644 | char *s, *d; | ||
645 | |||
646 | if (((char *)src + sizeof(char)) > (char *)src_end) | ||
647 | return -1; | ||
648 | |||
649 | s = (char *)src; | ||
650 | d = (char *)dst; | ||
651 | *d = *s; | ||
652 | CONV8(*d); | ||
653 | return sizeof(char); | ||
654 | } /* eet_data_get_char */ | ||
655 | |||
656 | static void * | ||
657 | eet_data_put_char(Eet_Dictionary *ed __UNUSED__, | ||
658 | const void *src, | ||
659 | int *size_ret) | ||
660 | { | ||
661 | char *s, *d; | ||
662 | |||
663 | d = (char *)malloc(sizeof(char)); | ||
664 | if (!d) | ||
665 | return NULL; | ||
666 | |||
667 | s = (char *)src; | ||
668 | *d = *s; | ||
669 | CONV8(*d); | ||
670 | *size_ret = sizeof(char); | ||
671 | return d; | ||
672 | } /* eet_data_put_char */ | ||
673 | |||
674 | /* SHORT TYPE */ | ||
675 | static int | ||
676 | eet_data_get_short(const Eet_Dictionary *ed __UNUSED__, | ||
677 | const void *src, | ||
678 | const void *src_end, | ||
679 | void *dst) | ||
680 | { | ||
681 | short *d; | ||
682 | |||
683 | if (((char *)src + sizeof(short)) > (char *)src_end) | ||
684 | return -1; | ||
685 | |||
686 | memcpy(dst, src, sizeof(short)); | ||
687 | d = (short *)dst; | ||
688 | CONV16(*d); | ||
689 | return sizeof(short); | ||
690 | } /* eet_data_get_short */ | ||
691 | |||
692 | static void * | ||
693 | eet_data_put_short(Eet_Dictionary *ed __UNUSED__, | ||
694 | const void *src, | ||
695 | int *size_ret) | ||
696 | { | ||
697 | short *s, *d; | ||
698 | |||
699 | d = (short *)malloc(sizeof(short)); | ||
700 | if (!d) | ||
701 | return NULL; | ||
702 | |||
703 | s = (short *)src; | ||
704 | *d = *s; | ||
705 | CONV16(*d); | ||
706 | *size_ret = sizeof(short); | ||
707 | return d; | ||
708 | } /* eet_data_put_short */ | ||
709 | |||
710 | /* INT TYPE */ | ||
711 | static inline int | ||
712 | eet_data_get_int(const Eet_Dictionary *ed __UNUSED__, | ||
713 | const void *src, | ||
714 | const void *src_end, | ||
715 | void *dst) | ||
716 | { | ||
717 | int *d; | ||
718 | |||
719 | if (((char *)src + sizeof(int)) > (char *)src_end) | ||
720 | return -1; | ||
721 | |||
722 | memcpy(dst, src, sizeof(int)); | ||
723 | d = (int *)dst; | ||
724 | CONV32(*d); | ||
725 | return sizeof(int); | ||
726 | } /* eet_data_get_int */ | ||
727 | |||
728 | static void * | ||
729 | eet_data_put_int(Eet_Dictionary *ed __UNUSED__, | ||
730 | const void *src, | ||
731 | int *size_ret) | ||
732 | { | ||
733 | int *s, *d; | ||
734 | |||
735 | d = (int *)malloc(sizeof(int)); | ||
736 | if (!d) | ||
737 | return NULL; | ||
738 | |||
739 | s = (int *)src; | ||
740 | *d = *s; | ||
741 | CONV32(*d); | ||
742 | *size_ret = sizeof(int); | ||
743 | return d; | ||
744 | } /* eet_data_put_int */ | ||
745 | |||
746 | /* LONG LONG TYPE */ | ||
747 | static int | ||
748 | eet_data_get_long_long(const Eet_Dictionary *ed __UNUSED__, | ||
749 | const void *src, | ||
750 | const void *src_end, | ||
751 | void *dst) | ||
752 | { | ||
753 | unsigned long long *d; | ||
754 | |||
755 | if (((char *)src + sizeof(unsigned long long)) > (char *)src_end) | ||
756 | return -1; | ||
757 | |||
758 | memcpy(dst, src, sizeof(unsigned long long)); | ||
759 | d = (unsigned long long *)dst; | ||
760 | CONV64(*d); | ||
761 | return sizeof(unsigned long long); | ||
762 | } /* eet_data_get_long_long */ | ||
763 | |||
764 | static void * | ||
765 | eet_data_put_long_long(Eet_Dictionary *ed __UNUSED__, | ||
766 | const void *src, | ||
767 | int *size_ret) | ||
768 | { | ||
769 | unsigned long long *s, *d; | ||
770 | |||
771 | d = (unsigned long long *)malloc(sizeof(unsigned long long)); | ||
772 | if (!d) | ||
773 | return NULL; | ||
774 | |||
775 | s = (unsigned long long *)src; | ||
776 | *d = *s; | ||
777 | CONV64(*d); | ||
778 | *size_ret = sizeof(unsigned long long); | ||
779 | return d; | ||
780 | } /* eet_data_put_long_long */ | ||
781 | |||
782 | /* STRING TYPE */ | ||
783 | static inline int | ||
784 | eet_data_get_string_hash(const Eet_Dictionary *ed, | ||
785 | const void *src, | ||
786 | const void *src_end) | ||
787 | { | ||
788 | if (ed) | ||
789 | { | ||
790 | int idx; | ||
791 | |||
792 | if (eet_data_get_int(ed, src, src_end, &idx) < 0) | ||
793 | return -1; | ||
794 | |||
795 | return eet_dictionary_string_get_hash(ed, idx); | ||
796 | } | ||
797 | |||
798 | return -1; | ||
799 | } /* eet_data_get_string_hash */ | ||
800 | |||
801 | static inline int | ||
802 | eet_data_get_string(const Eet_Dictionary *ed, | ||
803 | const void *src, | ||
804 | const void *src_end, | ||
805 | void *dst) | ||
806 | { | ||
807 | char *s, **d; | ||
808 | |||
809 | d = (char **)dst; | ||
810 | |||
811 | if (ed) | ||
812 | { | ||
813 | const char *str; | ||
814 | int idx; | ||
815 | |||
816 | if (eet_data_get_int(ed, src, src_end, &idx) < 0) | ||
817 | return -1; | ||
818 | |||
819 | str = eet_dictionary_string_get_char(ed, idx); | ||
820 | if (!str) | ||
821 | return -1; | ||
822 | |||
823 | *d = (char *)str; | ||
824 | return eet_dictionary_string_get_size(ed, idx); | ||
825 | } | ||
826 | |||
827 | s = (char *)src; | ||
828 | if (!s) | ||
829 | { | ||
830 | *d = NULL; | ||
831 | return 0; | ||
832 | } | ||
833 | |||
834 | *d = s; | ||
835 | return strlen(s) + 1; | ||
836 | } /* eet_data_get_string */ | ||
837 | |||
838 | static void * | ||
839 | eet_data_put_string(Eet_Dictionary *ed, | ||
840 | const void *src, | ||
841 | int *size_ret) | ||
842 | { | ||
843 | char *s, *d; | ||
844 | int len; | ||
845 | |||
846 | if (ed) | ||
847 | { | ||
848 | const char *str; | ||
849 | int idx; | ||
850 | |||
851 | str = *((const char **)src); | ||
852 | if (!str) | ||
853 | return NULL; | ||
854 | |||
855 | idx = eet_dictionary_string_add(ed, str); | ||
856 | if (idx == -1) | ||
857 | return NULL; | ||
858 | |||
859 | return eet_data_put_int(ed, &idx, size_ret); | ||
860 | } | ||
861 | |||
862 | s = (char *)(*((char **)src)); | ||
863 | if (!s) | ||
864 | return NULL; | ||
865 | |||
866 | len = strlen(s); | ||
867 | d = malloc(len + 1); | ||
868 | if (!d) | ||
869 | return NULL; | ||
870 | |||
871 | memcpy(d, s, len + 1); | ||
872 | *size_ret = len + 1; | ||
873 | return d; | ||
874 | } /* eet_data_put_string */ | ||
875 | |||
876 | /* ALWAYS INLINED STRING TYPE */ | ||
877 | static int | ||
878 | eet_data_get_istring(const Eet_Dictionary *ed __UNUSED__, | ||
879 | const void *src, | ||
880 | const void *src_end, | ||
881 | void *dst) | ||
882 | { | ||
883 | return eet_data_get_string(NULL, src, src_end, dst); | ||
884 | } /* eet_data_get_istring */ | ||
885 | |||
886 | static void * | ||
887 | eet_data_put_istring(Eet_Dictionary *ed __UNUSED__, | ||
888 | const void *src, | ||
889 | int *size_ret) | ||
890 | { | ||
891 | return eet_data_put_string(NULL, src, size_ret); | ||
892 | } /* eet_data_put_istring */ | ||
893 | |||
894 | /* ALWAYS NULL TYPE */ | ||
895 | static int | ||
896 | eet_data_get_null(const Eet_Dictionary *ed __UNUSED__, | ||
897 | const void *src __UNUSED__, | ||
898 | const void *src_end __UNUSED__, | ||
899 | void *dst) | ||
900 | { | ||
901 | char **d; | ||
902 | |||
903 | d = (char **)dst; | ||
904 | |||
905 | *d = NULL; | ||
906 | return 1; | ||
907 | } /* eet_data_get_null */ | ||
908 | |||
909 | static void * | ||
910 | eet_data_put_null(Eet_Dictionary *ed __UNUSED__, | ||
911 | const void *src __UNUSED__, | ||
912 | int *size_ret) | ||
913 | { | ||
914 | *size_ret = 0; | ||
915 | return NULL; | ||
916 | } /* eet_data_put_null */ | ||
917 | |||
918 | /** | ||
919 | * Fast lookups of simple doubles/floats. | ||
920 | * | ||
921 | * These aren't properly a cache because they don't store pre-calculated | ||
922 | * values, but have a so simple math that is almost as fast. | ||
923 | */ | ||
924 | static inline int | ||
925 | _eet_data_float_cache_get(const char *s, | ||
926 | int len, | ||
927 | float *d) | ||
928 | { | ||
929 | /* fast handle of simple case 0xMp+E*/ | ||
930 | if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p')) | ||
931 | { | ||
932 | int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0'); | ||
933 | int exponent = (s[5] - '0'); | ||
934 | |||
935 | if (s[4] == '+') | ||
936 | *d = (float)(mantisse << exponent); | ||
937 | else | ||
938 | *d = (float)mantisse / (float)(1 << exponent); | ||
939 | |||
940 | return 1; | ||
941 | } | ||
942 | |||
943 | return 0; | ||
944 | } /* _eet_data_float_cache_get */ | ||
945 | |||
946 | static inline int | ||
947 | _eet_data_double_cache_get(const char *s, | ||
948 | int len, | ||
949 | double *d) | ||
950 | { | ||
951 | /* fast handle of simple case 0xMp+E*/ | ||
952 | if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p')) | ||
953 | { | ||
954 | int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0'); | ||
955 | int exponent = (s[5] - '0'); | ||
956 | |||
957 | if (s[4] == '+') | ||
958 | *d = (double)(mantisse << exponent); | ||
959 | else | ||
960 | *d = (double)mantisse / (double)(1 << exponent); | ||
961 | |||
962 | return 1; | ||
963 | } | ||
964 | |||
965 | return 0; | ||
966 | } /* _eet_data_double_cache_get */ | ||
967 | |||
968 | /* FLOAT TYPE */ | ||
969 | static int | ||
970 | eet_data_get_float(const Eet_Dictionary *ed, | ||
971 | const void *src, | ||
972 | const void *src_end, | ||
973 | void *dst) | ||
974 | { | ||
975 | float *d; | ||
976 | int idx; | ||
977 | |||
978 | d = (float *)dst; | ||
979 | if (!ed) | ||
980 | { | ||
981 | const char *s, *p; | ||
982 | long long mantisse; | ||
983 | long exponent; | ||
984 | int len; | ||
985 | |||
986 | s = (const char *)src; | ||
987 | p = s; | ||
988 | len = 0; | ||
989 | while ((p < (const char *)src_end) && (*p != 0)) {len++; p++; } | ||
990 | |||
991 | if (_eet_data_float_cache_get(s, len, d) != 0) | ||
992 | return len + 1; | ||
993 | |||
994 | if (eina_convert_atod(s, len, &mantisse, &exponent) == EINA_FALSE) | ||
995 | return -1; | ||
996 | |||
997 | *d = (float)ldexp((double)mantisse, exponent); | ||
998 | |||
999 | return len + 1; | ||
1000 | } | ||
1001 | |||
1002 | if (eet_data_get_int(ed, src, src_end, &idx) < 0) | ||
1003 | return -1; | ||
1004 | |||
1005 | if (!eet_dictionary_string_get_float(ed, idx, d)) | ||
1006 | return -1; | ||
1007 | |||
1008 | return 1; | ||
1009 | } /* eet_data_get_float */ | ||
1010 | |||
1011 | static void * | ||
1012 | eet_data_put_float(Eet_Dictionary *ed, | ||
1013 | const void *src, | ||
1014 | int *size_ret) | ||
1015 | { | ||
1016 | char buf[128]; | ||
1017 | int idx; | ||
1018 | |||
1019 | eina_convert_dtoa((double)(*(float *)src), buf); | ||
1020 | |||
1021 | if (!ed) | ||
1022 | { | ||
1023 | char *d; | ||
1024 | int len; | ||
1025 | |||
1026 | len = strlen(buf); | ||
1027 | d = malloc(len + 1); | ||
1028 | if (!d) | ||
1029 | return NULL; | ||
1030 | |||
1031 | memcpy(d, buf, len + 1); | ||
1032 | *size_ret = len + 1; | ||
1033 | return d; | ||
1034 | } | ||
1035 | |||
1036 | idx = eet_dictionary_string_add(ed, buf); | ||
1037 | if (idx == -1) | ||
1038 | return NULL; | ||
1039 | |||
1040 | return eet_data_put_int(ed, &idx, size_ret); | ||
1041 | } /* eet_data_put_float */ | ||
1042 | |||
1043 | /* DOUBLE TYPE */ | ||
1044 | static int | ||
1045 | eet_data_get_double(const Eet_Dictionary *ed, | ||
1046 | const void *src, | ||
1047 | const void *src_end, | ||
1048 | void *dst) | ||
1049 | { | ||
1050 | double *d; | ||
1051 | int idx; | ||
1052 | |||
1053 | d = (double *)dst; | ||
1054 | |||
1055 | if (!ed) | ||
1056 | { | ||
1057 | const char *s, *p; | ||
1058 | long long mantisse = 0; | ||
1059 | long exponent = 0; | ||
1060 | int len; | ||
1061 | |||
1062 | s = (const char *)src; | ||
1063 | p = s; | ||
1064 | len = 0; | ||
1065 | while ((p < (const char *)src_end) && (*p != 0)) {len++; p++; } | ||
1066 | |||
1067 | if (_eet_data_double_cache_get(s, len, d) != 0) | ||
1068 | return len + 1; | ||
1069 | |||
1070 | if (eina_convert_atod(s, len, &mantisse, &exponent) == EINA_FALSE) | ||
1071 | return -1; | ||
1072 | |||
1073 | *d = ldexp((double)mantisse, exponent); | ||
1074 | |||
1075 | return len + 1; | ||
1076 | } | ||
1077 | |||
1078 | if (eet_data_get_int(ed, src, src_end, &idx) < 0) | ||
1079 | return -1; | ||
1080 | |||
1081 | if (!eet_dictionary_string_get_double(ed, idx, d)) | ||
1082 | return -1; | ||
1083 | |||
1084 | return 1; | ||
1085 | } /* eet_data_get_double */ | ||
1086 | |||
1087 | static void * | ||
1088 | eet_data_put_double(Eet_Dictionary *ed, | ||
1089 | const void *src, | ||
1090 | int *size_ret) | ||
1091 | { | ||
1092 | char buf[128]; | ||
1093 | int idx; | ||
1094 | |||
1095 | eina_convert_dtoa((double)(*(double *)src), buf); | ||
1096 | |||
1097 | if (!ed) | ||
1098 | { | ||
1099 | char *d; | ||
1100 | int len; | ||
1101 | |||
1102 | len = strlen(buf); | ||
1103 | d = malloc(len + 1); | ||
1104 | if (!d) | ||
1105 | return NULL; | ||
1106 | |||
1107 | memcpy(d, buf, len + 1); | ||
1108 | *size_ret = len + 1; | ||
1109 | |||
1110 | return d; | ||
1111 | } | ||
1112 | |||
1113 | idx = eet_dictionary_string_add(ed, buf); | ||
1114 | if (idx == -1) | ||
1115 | return NULL; | ||
1116 | |||
1117 | return eet_data_put_int(ed, &idx, size_ret); | ||
1118 | } /* eet_data_put_double */ | ||
1119 | |||
1120 | static int | ||
1121 | eet_data_get_f32p32(const Eet_Dictionary *ed, | ||
1122 | const void *src, | ||
1123 | const void *src_end, | ||
1124 | void *dst) | ||
1125 | { | ||
1126 | Eina_F32p32 *fp; | ||
1127 | int idx; | ||
1128 | |||
1129 | fp = (Eina_F32p32 *)dst; | ||
1130 | |||
1131 | if (!ed) | ||
1132 | { | ||
1133 | const char *s, *p; | ||
1134 | int len; | ||
1135 | |||
1136 | s = (const char *)src; | ||
1137 | p = s; | ||
1138 | len = 0; | ||
1139 | while ((p < (const char *)src_end) && (*p != 0)) { len++; p++; } | ||
1140 | |||
1141 | if (!(eina_convert_atofp(s, len, fp))) | ||
1142 | return -1; | ||
1143 | |||
1144 | return 1; | ||
1145 | } | ||
1146 | |||
1147 | if (eet_data_get_int(ed, src, src_end, &idx) < 0) | ||
1148 | return -1; | ||
1149 | |||
1150 | if (!eet_dictionary_string_get_fp(ed, idx, fp)) | ||
1151 | return -1; | ||
1152 | |||
1153 | return 1; | ||
1154 | } /* eet_data_get_f32p32 */ | ||
1155 | |||
1156 | static void * | ||
1157 | eet_data_put_f32p32(Eet_Dictionary *ed, | ||
1158 | const void *src, | ||
1159 | int *size_ret) | ||
1160 | { | ||
1161 | char buf[128]; | ||
1162 | int idx; | ||
1163 | |||
1164 | eina_convert_fptoa((Eina_F32p32)(*(Eina_F32p32 *)src), buf); | ||
1165 | |||
1166 | if (!ed) | ||
1167 | { | ||
1168 | char *d; | ||
1169 | int len; | ||
1170 | |||
1171 | len = strlen(buf); | ||
1172 | d = malloc(len + 1); | ||
1173 | if (!d) | ||
1174 | return NULL; | ||
1175 | |||
1176 | memcpy(d, buf, len + 1); | ||
1177 | *size_ret = len + 1; | ||
1178 | |||
1179 | return d; | ||
1180 | } | ||
1181 | |||
1182 | idx = eet_dictionary_string_add(ed, buf); | ||
1183 | if (idx == -1) | ||
1184 | return NULL; | ||
1185 | |||
1186 | return eet_data_put_int(ed, &idx, size_ret); | ||
1187 | } /* eet_data_put_f32p32 */ | ||
1188 | |||
1189 | static int | ||
1190 | eet_data_get_f16p16(const Eet_Dictionary *ed, | ||
1191 | const void *src, | ||
1192 | const void *src_end, | ||
1193 | void *dst) | ||
1194 | { | ||
1195 | Eina_F32p32 tmp; | ||
1196 | Eina_F16p16 *fp; | ||
1197 | |||
1198 | fp = (Eina_F16p16 *)dst; | ||
1199 | |||
1200 | if (eet_data_get_f32p32(ed, src, src_end, &tmp) < 0) | ||
1201 | return -1; | ||
1202 | |||
1203 | *fp = eina_f32p32_to_f16p16(tmp); | ||
1204 | return 1; | ||
1205 | } /* eet_data_get_f16p16 */ | ||
1206 | |||
1207 | static void * | ||
1208 | eet_data_put_f16p16(Eet_Dictionary *ed, | ||
1209 | const void *src, | ||
1210 | int *size_ret) | ||
1211 | { | ||
1212 | Eina_F32p32 tmp; | ||
1213 | |||
1214 | tmp = eina_f16p16_to_f32p32((Eina_F16p16)(*(Eina_F16p16 *)src)); | ||
1215 | return eet_data_put_f32p32(ed, &tmp, size_ret); | ||
1216 | } /* eet_data_put_f16p16 */ | ||
1217 | |||
1218 | static int | ||
1219 | eet_data_get_f8p24(const Eet_Dictionary *ed, | ||
1220 | const void *src, | ||
1221 | const void *src_end, | ||
1222 | void *dst) | ||
1223 | { | ||
1224 | Eina_F32p32 tmp; | ||
1225 | Eina_F8p24 *fp; | ||
1226 | |||
1227 | fp = (Eina_F8p24 *)dst; | ||
1228 | |||
1229 | if (eet_data_get_f32p32(ed, src, src_end, &tmp) < 0) | ||
1230 | return -1; | ||
1231 | |||
1232 | *fp = eina_f32p32_to_f8p24(tmp); | ||
1233 | return 1; | ||
1234 | } /* eet_data_get_f8p24 */ | ||
1235 | |||
1236 | static void * | ||
1237 | eet_data_put_f8p24(Eet_Dictionary *ed, | ||
1238 | const void *src, | ||
1239 | int *size_ret) | ||
1240 | { | ||
1241 | Eina_F32p32 tmp; | ||
1242 | |||
1243 | tmp = eina_f8p24_to_f32p32((Eina_F8p24)(*(Eina_F8p24 *)src)); | ||
1244 | return eet_data_put_f32p32(ed, &tmp, size_ret); | ||
1245 | } /* eet_data_put_f8p24 */ | ||
1246 | |||
1247 | static inline int | ||
1248 | eet_data_get_type(const Eet_Dictionary *ed, | ||
1249 | int type, | ||
1250 | const void *src, | ||
1251 | const void *src_end, | ||
1252 | void *dest) | ||
1253 | { | ||
1254 | int ret; | ||
1255 | |||
1256 | ret = eet_basic_codec[type - 1].get(ed, src, src_end, dest); | ||
1257 | return ret; | ||
1258 | } /* eet_data_get_type */ | ||
1259 | |||
1260 | static inline void * | ||
1261 | eet_data_put_type(Eet_Dictionary *ed, | ||
1262 | int type, | ||
1263 | const void *src, | ||
1264 | int *size_ret) | ||
1265 | { | ||
1266 | void *ret; | ||
1267 | |||
1268 | ret = eet_basic_codec[type - 1].put(ed, src, size_ret); | ||
1269 | return ret; | ||
1270 | } /* eet_data_put_type */ | ||
1271 | |||
1272 | static inline Eina_Bool | ||
1273 | eet_data_type_match(int type1, | ||
1274 | int type2) | ||
1275 | { | ||
1276 | if (type1 == type2) | ||
1277 | return EINA_TRUE; | ||
1278 | |||
1279 | /* Note: All floating point type are equivalent and could be read | ||
1280 | without problem by any other floating point getter. */ | ||
1281 | switch (type1) | ||
1282 | { | ||
1283 | case EET_T_FLOAT: | ||
1284 | case EET_T_DOUBLE: | ||
1285 | case EET_T_F32P32: | ||
1286 | case EET_T_F16P16: | ||
1287 | case EET_T_F8P24: | ||
1288 | switch (type2) | ||
1289 | { | ||
1290 | case EET_T_FLOAT: | ||
1291 | case EET_T_DOUBLE: | ||
1292 | case EET_T_F32P32: | ||
1293 | case EET_T_F16P16: | ||
1294 | case EET_T_F8P24: | ||
1295 | return EINA_TRUE; | ||
1296 | |||
1297 | default: | ||
1298 | break; | ||
1299 | } /* switch */ | ||
1300 | break; | ||
1301 | |||
1302 | default: | ||
1303 | break; | ||
1304 | } /* switch */ | ||
1305 | |||
1306 | return EINA_FALSE; | ||
1307 | } /* eet_data_type_match */ | ||
1308 | |||
1309 | /* chunk format... | ||
1310 | * | ||
1311 | * char[4] = "CHnK"; // untyped data ... or | ||
1312 | * char[4] = "CHKx"; // typed data - x == type | ||
1313 | * | ||
1314 | * int = chunk size (including magic string); | ||
1315 | * char[] = chunk magic/name string (0 byte terminated); | ||
1316 | * ... sub-chunks (a chunk can contain chuncks recusrively) ... | ||
1317 | * or | ||
1318 | * ... payload data ... | ||
1319 | * | ||
1320 | */ | ||
1321 | |||
1322 | static inline void | ||
1323 | eet_data_chunk_get(const Eet_Dictionary *ed, | ||
1324 | Eet_Data_Chunk *chnk, | ||
1325 | const void *src, | ||
1326 | int size) | ||
1327 | { | ||
1328 | const char *s; | ||
1329 | int ret1, ret2; | ||
1330 | |||
1331 | if (!src) | ||
1332 | return; | ||
1333 | |||
1334 | if (size <= 8) | ||
1335 | return; | ||
1336 | |||
1337 | if (!chnk) | ||
1338 | return; | ||
1339 | |||
1340 | s = src; | ||
1341 | if (s[2] == 'K') | ||
1342 | { | ||
1343 | if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'K')) | ||
1344 | return; | ||
1345 | |||
1346 | chnk->type = (unsigned char)(s[3]); | ||
1347 | if (chnk->type >= EET_I_LIMIT) | ||
1348 | { | ||
1349 | chnk->group_type = | ||
1350 | ((chnk->type - EET_I_LIMIT) & 0xF) + EET_G_UNKNOWN; | ||
1351 | switch ((chnk->type - EET_I_LIMIT) & 0xF0) | ||
1352 | { | ||
1353 | #define EET_UNMATCH_TYPE(Type) \ | ||
1354 | case EET_I_ ## Type: chnk->type = EET_T_ ## Type; break; | ||
1355 | |||
1356 | EET_UNMATCH_TYPE(STRING); | ||
1357 | EET_UNMATCH_TYPE(INLINED_STRING); | ||
1358 | EET_UNMATCH_TYPE(NULL); | ||
1359 | |||
1360 | default: | ||
1361 | return; | ||
1362 | } /* switch */ | ||
1363 | } | ||
1364 | else if (chnk->type > EET_T_LAST) | ||
1365 | { | ||
1366 | chnk->group_type = chnk->type; | ||
1367 | chnk->type = EET_T_UNKNOW; | ||
1368 | } | ||
1369 | else | ||
1370 | chnk->group_type = EET_G_UNKNOWN; | ||
1371 | if ((chnk->type >= EET_T_LAST) || | ||
1372 | (chnk->group_type >= | ||
1373 | EET_G_LAST)) | ||
1374 | { | ||
1375 | chnk->type = 0; | ||
1376 | chnk->group_type = 0; | ||
1377 | } | ||
1378 | } | ||
1379 | else if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'n') || (s[3] != 'K')) | ||
1380 | return; | ||
1381 | |||
1382 | ret1 = eet_data_get_type(ed, EET_T_INT, (s + 4), (s + size), &(chnk->size)); | ||
1383 | |||
1384 | if (ret1 <= 0) | ||
1385 | return; | ||
1386 | |||
1387 | if ((chnk->size < 0) || ((chnk->size + 8) > size)) | ||
1388 | return; | ||
1389 | |||
1390 | ret2 = eet_data_get_type(ed, EET_T_STRING, (s + 8), (s + size), &(chnk->name)); | ||
1391 | |||
1392 | if (ret2 <= 0) | ||
1393 | return; | ||
1394 | |||
1395 | chnk->len = ret2; | ||
1396 | |||
1397 | /* Precalc hash */ | ||
1398 | chnk->hash = eet_data_get_string_hash(ed, (s + 8), (s + size)); | ||
1399 | |||
1400 | if (ed) | ||
1401 | { | ||
1402 | chnk->data = (char *)src + 4 + ret1 + sizeof(int); | ||
1403 | chnk->size -= sizeof(int); | ||
1404 | } | ||
1405 | else | ||
1406 | { | ||
1407 | chnk->data = (char *)src + 4 + ret1 + chnk->len; | ||
1408 | chnk->size -= chnk->len; | ||
1409 | } | ||
1410 | |||
1411 | return; | ||
1412 | } /* eet_data_chunk_get */ | ||
1413 | |||
1414 | static inline Eet_Data_Chunk * | ||
1415 | eet_data_chunk_new(void *data, | ||
1416 | int size, | ||
1417 | const char *name, | ||
1418 | int type, | ||
1419 | int group_type) | ||
1420 | { | ||
1421 | Eet_Data_Chunk *chnk; | ||
1422 | |||
1423 | if (!name) | ||
1424 | return NULL; | ||
1425 | |||
1426 | chnk = calloc(1, sizeof(Eet_Data_Chunk)); | ||
1427 | if (!chnk) | ||
1428 | return NULL; | ||
1429 | |||
1430 | /* Note: Another security, so older eet library could read file | ||
1431 | saved with fixed point value. */ | ||
1432 | if (type == EET_T_F32P32 | ||
1433 | || type == EET_T_F16P16 | ||
1434 | || type == EET_T_F8P24) | ||
1435 | type = EET_T_DOUBLE; | ||
1436 | |||
1437 | chnk->name = strdup(name); | ||
1438 | chnk->len = strlen(name) + 1; | ||
1439 | chnk->size = size; | ||
1440 | chnk->data = data; | ||
1441 | chnk->type = type; | ||
1442 | chnk->group_type = group_type; | ||
1443 | return chnk; | ||
1444 | } /* eet_data_chunk_new */ | ||
1445 | |||
1446 | static inline void | ||
1447 | eet_data_chunk_free(Eet_Data_Chunk *chnk) | ||
1448 | { | ||
1449 | if (chnk->name) | ||
1450 | free(chnk->name); | ||
1451 | |||
1452 | free(chnk); | ||
1453 | } /* eet_data_chunk_free */ | ||
1454 | |||
1455 | static inline Eet_Data_Stream * | ||
1456 | eet_data_stream_new(void) | ||
1457 | { | ||
1458 | Eet_Data_Stream *ds; | ||
1459 | |||
1460 | ds = calloc(1, sizeof(Eet_Data_Stream)); | ||
1461 | if (!ds) | ||
1462 | return NULL; | ||
1463 | |||
1464 | return ds; | ||
1465 | } /* eet_data_stream_new */ | ||
1466 | |||
1467 | static inline void | ||
1468 | eet_data_stream_free(Eet_Data_Stream *ds) | ||
1469 | { | ||
1470 | if (ds->data) | ||
1471 | free(ds->data); | ||
1472 | |||
1473 | free(ds); | ||
1474 | } /* eet_data_stream_free */ | ||
1475 | |||
1476 | static inline void | ||
1477 | eet_data_stream_flush(Eet_Data_Stream *ds) | ||
1478 | { | ||
1479 | free(ds); | ||
1480 | } /* eet_data_stream_flush */ | ||
1481 | |||
1482 | static inline void | ||
1483 | eet_data_stream_write(Eet_Data_Stream *ds, | ||
1484 | const void *data, | ||
1485 | int size) | ||
1486 | { | ||
1487 | char *p; | ||
1488 | |||
1489 | if ((ds->pos + size) > ds->size) | ||
1490 | { | ||
1491 | ds->data = realloc(ds->data, ds->size + size + 512); | ||
1492 | if (!ds->data) | ||
1493 | { | ||
1494 | ds->pos = 0; | ||
1495 | ds->size = 0; | ||
1496 | return; | ||
1497 | } | ||
1498 | |||
1499 | ds->size = ds->size + size + 512; | ||
1500 | } | ||
1501 | |||
1502 | p = ds->data; | ||
1503 | memcpy(p + ds->pos, data, size); | ||
1504 | ds->pos += size; | ||
1505 | } /* eet_data_stream_write */ | ||
1506 | |||
1507 | static void | ||
1508 | eet_data_chunk_put(Eet_Dictionary *ed, | ||
1509 | Eet_Data_Chunk *chnk, | ||
1510 | Eet_Data_Stream *ds) | ||
1511 | { | ||
1512 | int *size; | ||
1513 | void *string; | ||
1514 | int s; | ||
1515 | int size_ret = 0; | ||
1516 | int string_ret = 0; | ||
1517 | unsigned char buf[4] = "CHK"; | ||
1518 | |||
1519 | /* disable this check - it will allow empty chunks to be written. this is | ||
1520 | * right for corner-cases when y have a struct with empty fields (empty | ||
1521 | * strings or empty list ptrs etc.) */ | ||
1522 | /* if (!chnk->data && chnk->type != EET_T_NULL) return; */ | ||
1523 | /* chunk head */ | ||
1524 | |||
1525 | /* eet_data_stream_write(ds, "CHnK", 4);*/ | ||
1526 | if (chnk->type != EET_T_UNKNOW) | ||
1527 | { | ||
1528 | if (chnk->group_type != EET_G_UNKNOWN) | ||
1529 | { | ||
1530 | int type = EET_I_LIMIT + chnk->group_type - EET_G_UNKNOWN; | ||
1531 | |||
1532 | switch (chnk->type) | ||
1533 | { | ||
1534 | /* Only make sense with pointer type. */ | ||
1535 | #define EET_MATCH_TYPE(Type) \ | ||
1536 | case EET_T_ ## Type: type += EET_I_ ## Type; break; | ||
1537 | |||
1538 | EET_MATCH_TYPE(STRING); | ||
1539 | EET_MATCH_TYPE(INLINED_STRING); | ||
1540 | EET_MATCH_TYPE(NULL); | ||
1541 | |||
1542 | default: | ||
1543 | return; | ||
1544 | } /* switch */ | ||
1545 | |||
1546 | buf[3] = type; | ||
1547 | } | ||
1548 | else | ||
1549 | buf[3] = chnk->type; | ||
1550 | } | ||
1551 | else | ||
1552 | buf[3] = chnk->group_type; | ||
1553 | |||
1554 | string = eet_data_put_string(ed, &chnk->name, &string_ret); | ||
1555 | if (!string) | ||
1556 | return; | ||
1557 | |||
1558 | /* size of chunk payload data + name */ | ||
1559 | s = chnk->size + string_ret; | ||
1560 | size = eet_data_put_int(ed, &s, &size_ret); | ||
1561 | |||
1562 | /* FIXME: If something goes wrong the resulting file will be corrupted. */ | ||
1563 | if (!size) | ||
1564 | goto on_error; | ||
1565 | |||
1566 | eet_data_stream_write(ds, buf, 4); | ||
1567 | |||
1568 | /* write chunk length */ | ||
1569 | eet_data_stream_write(ds, size, size_ret); | ||
1570 | |||
1571 | /* write chunk name */ | ||
1572 | eet_data_stream_write(ds, string, string_ret); | ||
1573 | |||
1574 | /* write payload */ | ||
1575 | if (chnk->data) | ||
1576 | eet_data_stream_write(ds, chnk->data, chnk->size); | ||
1577 | |||
1578 | free(string); | ||
1579 | on_error: | ||
1580 | free(size); | ||
1581 | } /* eet_data_chunk_put */ | ||
1582 | |||
1583 | /*---*/ | ||
1584 | |||
1585 | static void | ||
1586 | _eet_descriptor_hash_new(Eet_Data_Descriptor *edd) | ||
1587 | { | ||
1588 | int i; | ||
1589 | |||
1590 | edd->elements.hash.size = 1 << 6; | ||
1591 | edd->elements.hash.buckets = calloc( | ||
1592 | 1, | ||
1593 | sizeof(Eet_Data_Descriptor_Hash) * | ||
1594 | edd->elements.hash.size); | ||
1595 | for (i = 0; i < edd->elements.num; i++) | ||
1596 | { | ||
1597 | Eet_Data_Element *ede; | ||
1598 | int hash; | ||
1599 | |||
1600 | ede = &(edd->elements.set[i]); | ||
1601 | hash = _eet_hash_gen((char *)ede->name, 6); | ||
1602 | if (!edd->elements.hash.buckets[hash].element) | ||
1603 | edd->elements.hash.buckets[hash].element = ede; | ||
1604 | else | ||
1605 | { | ||
1606 | Eet_Data_Descriptor_Hash *bucket; | ||
1607 | |||
1608 | bucket = calloc(1, sizeof(Eet_Data_Descriptor_Hash)); | ||
1609 | bucket->element = ede; | ||
1610 | bucket->next = edd->elements.hash.buckets[hash].next; | ||
1611 | edd->elements.hash.buckets[hash].next = bucket; | ||
1612 | } | ||
1613 | } | ||
1614 | } /* _eet_descriptor_hash_new */ | ||
1615 | |||
1616 | static void | ||
1617 | _eet_descriptor_hash_free(Eet_Data_Descriptor *edd) | ||
1618 | { | ||
1619 | int i; | ||
1620 | |||
1621 | for (i = 0; i < edd->elements.hash.size; i++) | ||
1622 | { | ||
1623 | Eet_Data_Descriptor_Hash *bucket, *pbucket; | ||
1624 | |||
1625 | bucket = edd->elements.hash.buckets[i].next; | ||
1626 | while (bucket) | ||
1627 | { | ||
1628 | pbucket = bucket; | ||
1629 | bucket = bucket->next; | ||
1630 | free(pbucket); | ||
1631 | } | ||
1632 | } | ||
1633 | if (edd->elements.hash.buckets) | ||
1634 | free(edd->elements.hash.buckets); | ||
1635 | } /* _eet_descriptor_hash_free */ | ||
1636 | |||
1637 | static Eet_Data_Element * | ||
1638 | _eet_descriptor_hash_find(Eet_Data_Descriptor *edd, | ||
1639 | char *name, | ||
1640 | int hash) | ||
1641 | { | ||
1642 | Eet_Data_Descriptor_Hash *bucket; | ||
1643 | |||
1644 | if (hash < 0) | ||
1645 | hash = _eet_hash_gen(name, 6); | ||
1646 | else | ||
1647 | hash &= 0x3f; | ||
1648 | |||
1649 | if (!edd->elements.hash.buckets[hash].element) | ||
1650 | return NULL; /* | ||
1651 | When we use the dictionary as a source for chunk name, we will always | ||
1652 | have the same pointer in name. It's a good idea to just compare pointer | ||
1653 | instead of running strcmp on both string. | ||
1654 | */ | ||
1655 | |||
1656 | if (edd->elements.hash.buckets[hash].element->directory_name_ptr == name) | ||
1657 | return edd->elements.hash.buckets[hash].element; | ||
1658 | |||
1659 | if (!strcmp(edd->elements.hash.buckets[hash].element->name, name)) | ||
1660 | { | ||
1661 | edd->elements.hash.buckets[hash].element->directory_name_ptr = name; | ||
1662 | return edd->elements.hash.buckets[hash].element; | ||
1663 | } | ||
1664 | |||
1665 | bucket = edd->elements.hash.buckets[hash].next; | ||
1666 | while (bucket) | ||
1667 | { | ||
1668 | if (bucket->element->directory_name_ptr == name) | ||
1669 | return bucket->element; | ||
1670 | |||
1671 | if (!strcmp(bucket->element->name, name)) | ||
1672 | { | ||
1673 | bucket->element->directory_name_ptr = name; | ||
1674 | return bucket->element; | ||
1675 | } | ||
1676 | |||
1677 | bucket = bucket->next; | ||
1678 | } | ||
1679 | return NULL; | ||
1680 | } /* _eet_descriptor_hash_find */ | ||
1681 | |||
1682 | static void * | ||
1683 | _eet_mem_alloc(size_t size) | ||
1684 | { | ||
1685 | return calloc(1, size); | ||
1686 | } /* _eet_mem_alloc */ | ||
1687 | |||
1688 | static void | ||
1689 | _eet_mem_free(void *mem) | ||
1690 | { | ||
1691 | free(mem); | ||
1692 | } /* _eet_mem_free */ | ||
1693 | |||
1694 | static char * | ||
1695 | _eet_str_alloc(const char *str) | ||
1696 | { | ||
1697 | return strdup(str); | ||
1698 | } /* _eet_str_alloc */ | ||
1699 | |||
1700 | static void | ||
1701 | _eet_str_free(const char *str) | ||
1702 | { | ||
1703 | free((char *)str); | ||
1704 | } /* _eet_str_free */ | ||
1705 | |||
1706 | static Eina_Hash * | ||
1707 | _eet_eina_hash_add_alloc(Eina_Hash *hash, | ||
1708 | const char *key, | ||
1709 | void *data) | ||
1710 | { | ||
1711 | if (!hash) | ||
1712 | hash = eina_hash_string_small_new(NULL); | ||
1713 | |||
1714 | if (!hash) | ||
1715 | return NULL; | ||
1716 | |||
1717 | eina_hash_add(hash, key, data); | ||
1718 | return hash; | ||
1719 | } /* _eet_eina_hash_add_alloc */ | ||
1720 | |||
1721 | static Eina_Hash * | ||
1722 | _eet_eina_hash_direct_add_alloc(Eina_Hash *hash, | ||
1723 | const char *key, | ||
1724 | void *data) | ||
1725 | { | ||
1726 | if (!hash) | ||
1727 | hash = eina_hash_string_small_new(NULL); | ||
1728 | |||
1729 | if (!hash) | ||
1730 | return NULL; | ||
1731 | |||
1732 | eina_hash_direct_add(hash, key, data); | ||
1733 | return hash; | ||
1734 | } /* _eet_eina_hash_direct_add_alloc */ | ||
1735 | |||
1736 | static char * | ||
1737 | _eet_str_direct_alloc(const char *str) | ||
1738 | { | ||
1739 | return (char *)str; | ||
1740 | } /* _eet_str_direct_alloc */ | ||
1741 | |||
1742 | static void | ||
1743 | _eet_str_direct_free(const char *str __UNUSED__) | ||
1744 | { | ||
1745 | } /* _eet_str_direct_free */ | ||
1746 | |||
1747 | static void | ||
1748 | _eet_eina_hash_foreach(void *hash, | ||
1749 | Eina_Hash_Foreach cb, | ||
1750 | void *fdata) | ||
1751 | { | ||
1752 | if (hash) | ||
1753 | eina_hash_foreach(hash, cb, fdata); | ||
1754 | } /* _eet_eina_hash_foreach */ | ||
1755 | |||
1756 | static void | ||
1757 | _eet_eina_hash_free(void *hash) | ||
1758 | { | ||
1759 | if (hash) | ||
1760 | eina_hash_free(hash); | ||
1761 | } /* _eet_eina_hash_free */ | ||
1762 | |||
1763 | /*---*/ | ||
1764 | EAPI Eina_Bool | ||
1765 | eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, | ||
1766 | /* When we change the structure content in the future, we need to handle old structure type too */ | ||
1767 | unsigned int eddc_size, | ||
1768 | const char *name, | ||
1769 | int size) | ||
1770 | { | ||
1771 | if (!eddc || !name || eddc_size != sizeof (Eet_Data_Descriptor_Class)) | ||
1772 | return EINA_FALSE; | ||
1773 | |||
1774 | eddc->name = name; | ||
1775 | eddc->size = size; | ||
1776 | eddc->version = EET_DATA_DESCRIPTOR_CLASS_VERSION; | ||
1777 | |||
1778 | eddc->func.mem_alloc = _eet_mem_alloc; | ||
1779 | eddc->func.mem_free = _eet_mem_free; | ||
1780 | eddc->func.str_alloc = (char *(*)(const char *))eina_stringshare_add; | ||
1781 | eddc->func.str_free = eina_stringshare_del; | ||
1782 | eddc->func.list_next = (void *(*)(void *))eina_list_next; | ||
1783 | eddc->func.list_append = (void *(*)(void *, void *))eina_list_append; | ||
1784 | eddc->func.list_data = (void *(*)(void *))eina_list_data_get; | ||
1785 | eddc->func.list_free = (void *(*)(void *))eina_list_free; | ||
1786 | eddc->func.hash_foreach = (void (*)(void *, int (*)(void *, const char *, void *, void *), void *))_eet_eina_hash_foreach; | ||
1787 | eddc->func.hash_add = (void *(*)(void *, const char *, void *))_eet_eina_hash_add_alloc; | ||
1788 | eddc->func.hash_free = (void (*)(void *))_eet_eina_hash_free; | ||
1789 | |||
1790 | /* This will cause an ABI incompatibility */ | ||
1791 | eddc->func.array_alloc = _eet_mem_alloc; | ||
1792 | eddc->func.array_free = _eet_mem_free; | ||
1793 | |||
1794 | return EINA_TRUE; | ||
1795 | } /* eet_eina_stream_data_descriptor_class_set */ | ||
1796 | |||
1797 | EAPI Eina_Bool | ||
1798 | eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, | ||
1799 | /* When we change the structure content in the future, we need to handle old structure type too */ | ||
1800 | unsigned int eddc_size, | ||
1801 | const char *name, | ||
1802 | int size) | ||
1803 | { | ||
1804 | if (!eet_eina_stream_data_descriptor_class_set(eddc, eddc_size, name, size)) | ||
1805 | return EINA_FALSE; | ||
1806 | |||
1807 | eddc->version = EET_DATA_DESCRIPTOR_CLASS_VERSION; | ||
1808 | |||
1809 | eddc->func.hash_add = (void *(*)(void *, const char *, void *))_eet_eina_hash_direct_add_alloc; | ||
1810 | eddc->func.str_direct_alloc = _eet_str_direct_alloc; | ||
1811 | eddc->func.str_direct_free = _eet_str_direct_free; | ||
1812 | |||
1813 | return EINA_TRUE; | ||
1814 | } /* eet_eina_file_data_descriptor_class_set */ | ||
1815 | |||
1816 | static Eet_Data_Descriptor * | ||
1817 | _eet_data_descriptor_new(const Eet_Data_Descriptor_Class *eddc, | ||
1818 | int version) | ||
1819 | { | ||
1820 | Eet_Data_Descriptor *edd; | ||
1821 | |||
1822 | if (!eddc) | ||
1823 | return NULL; | ||
1824 | |||
1825 | edd = calloc(1, sizeof (Eet_Data_Descriptor)); | ||
1826 | if (!edd) | ||
1827 | return NULL; | ||
1828 | |||
1829 | edd->name = eddc->name; | ||
1830 | edd->ed = NULL; | ||
1831 | edd->size = eddc->size; | ||
1832 | edd->func.mem_alloc = _eet_mem_alloc; | ||
1833 | edd->func.mem_free = _eet_mem_free; | ||
1834 | edd->func.str_alloc = _eet_str_alloc; | ||
1835 | edd->func.str_free = _eet_str_free; | ||
1836 | if (eddc->func.mem_alloc) | ||
1837 | edd->func.mem_alloc = eddc->func.mem_alloc; | ||
1838 | |||
1839 | if (eddc->func.mem_free) | ||
1840 | edd->func.mem_free = eddc->func.mem_free; | ||
1841 | |||
1842 | if (eddc->func.str_alloc) | ||
1843 | edd->func.str_alloc = eddc->func.str_alloc; | ||
1844 | |||
1845 | if (eddc->func.str_free) | ||
1846 | edd->func.str_free = eddc->func.str_free; | ||
1847 | |||
1848 | edd->func.list_next = eddc->func.list_next; | ||
1849 | edd->func.list_append = eddc->func.list_append; | ||
1850 | edd->func.list_data = eddc->func.list_data; | ||
1851 | edd->func.list_free = eddc->func.list_free; | ||
1852 | edd->func.hash_foreach = eddc->func.hash_foreach; | ||
1853 | edd->func.hash_add = eddc->func.hash_add; | ||
1854 | edd->func.hash_free = eddc->func.hash_free; | ||
1855 | |||
1856 | if (eddc->version > 1 && version > 1) | ||
1857 | { | ||
1858 | edd->func.str_direct_alloc = eddc->func.str_direct_alloc; | ||
1859 | edd->func.str_direct_free = eddc->func.str_direct_free; | ||
1860 | } | ||
1861 | |||
1862 | if (eddc->version > 2) | ||
1863 | { | ||
1864 | edd->func.type_get = eddc->func.type_get; | ||
1865 | edd->func.type_set = eddc->func.type_set; | ||
1866 | } | ||
1867 | |||
1868 | if (eddc->version > 3) | ||
1869 | { | ||
1870 | edd->func.array_alloc = eddc->func.array_alloc; | ||
1871 | edd->func.array_free = eddc->func.array_free; | ||
1872 | } | ||
1873 | |||
1874 | return edd; | ||
1875 | } /* _eet_data_descriptor_new */ | ||
1876 | |||
1877 | EAPI Eet_Data_Descriptor * | ||
1878 | eet_data_descriptor_new(const char *name, | ||
1879 | int size, | ||
1880 | Eet_Descriptor_List_Next_Callback func_list_next, | ||
1881 | Eet_Descriptor_List_Append_Callback func_list_append, | ||
1882 | Eet_Descriptor_List_Data_Callback func_list_data, | ||
1883 | Eet_Descriptor_List_Free_Callback func_list_free, | ||
1884 | Eet_Descriptor_Hash_Foreach_Callback func_hash_foreach, | ||
1885 | Eet_Descriptor_Hash_Add_Callback func_hash_add, | ||
1886 | Eet_Descriptor_Hash_Free_Callback func_hash_free) | ||
1887 | { | ||
1888 | Eet_Data_Descriptor_Class eddc; | ||
1889 | |||
1890 | if (!name) | ||
1891 | return NULL; | ||
1892 | |||
1893 | memset(&eddc, 0, sizeof (Eet_Data_Descriptor_Class)); | ||
1894 | |||
1895 | eddc.name = name; | ||
1896 | eddc.size = size; | ||
1897 | eddc.version = 0; | ||
1898 | |||
1899 | eddc.func.list_next = func_list_next; | ||
1900 | eddc.func.list_append = func_list_append; | ||
1901 | eddc.func.list_data = func_list_data; | ||
1902 | eddc.func.list_free = func_list_free; | ||
1903 | eddc.func.hash_foreach = func_hash_foreach; | ||
1904 | eddc.func.hash_add = func_hash_add; | ||
1905 | eddc.func.hash_free = func_hash_free; | ||
1906 | |||
1907 | return _eet_data_descriptor_new(&eddc, 0); | ||
1908 | } /* eet_data_descriptor_new */ | ||
1909 | |||
1910 | EAPI Eet_Data_Descriptor * | ||
1911 | eet_data_descriptor2_new(const Eet_Data_Descriptor_Class *eddc) | ||
1912 | { | ||
1913 | return _eet_data_descriptor_new(eddc, 1); | ||
1914 | } /* eet_data_descriptor2_new */ | ||
1915 | |||
1916 | EAPI Eet_Data_Descriptor * | ||
1917 | eet_data_descriptor3_new(const Eet_Data_Descriptor_Class *eddc) | ||
1918 | { | ||
1919 | return _eet_data_descriptor_new(eddc, 2); | ||
1920 | } /* eet_data_descriptor3_new */ | ||
1921 | |||
1922 | EAPI Eet_Data_Descriptor * | ||
1923 | eet_data_descriptor_stream_new(const Eet_Data_Descriptor_Class *eddc) | ||
1924 | { | ||
1925 | return _eet_data_descriptor_new(eddc, 1); | ||
1926 | } /* eet_data_descriptor_stream_new */ | ||
1927 | |||
1928 | EAPI Eet_Data_Descriptor * | ||
1929 | eet_data_descriptor_file_new(const Eet_Data_Descriptor_Class *eddc) | ||
1930 | { | ||
1931 | return _eet_data_descriptor_new(eddc, 2); | ||
1932 | } /* eet_data_descriptor_file_new */ | ||
1933 | |||
1934 | EAPI void | ||
1935 | eet_data_descriptor_free(Eet_Data_Descriptor *edd) | ||
1936 | { | ||
1937 | if (!edd) | ||
1938 | return; | ||
1939 | |||
1940 | _eet_descriptor_hash_free(edd); | ||
1941 | if (edd->elements.set) | ||
1942 | free(edd->elements.set); | ||
1943 | |||
1944 | free(edd); | ||
1945 | } /* eet_data_descriptor_free */ | ||
1946 | |||
1947 | EAPI void | ||
1948 | eet_data_descriptor_element_add(Eet_Data_Descriptor *edd, | ||
1949 | const char *name, | ||
1950 | int type, | ||
1951 | int group_type, | ||
1952 | int offset, | ||
1953 | int count, | ||
1954 | /* int counter_offset, */ | ||
1955 | const char *counter_name /* FIXME: Useless should go on a major release */, | ||
1956 | Eet_Data_Descriptor *subtype) | ||
1957 | { | ||
1958 | Eet_Data_Element *ede; | ||
1959 | Eet_Data_Element *tmp; | ||
1960 | |||
1961 | /* UNION, VARIANT type would not work with simple type, we need a way to map the type. */ | ||
1962 | if ((group_type == EET_G_UNION | ||
1963 | || group_type == EET_G_VARIANT) | ||
1964 | && | ||
1965 | (type != EET_T_UNKNOW | ||
1966 | || !subtype | ||
1967 | || !subtype->func.type_get | ||
1968 | || !subtype->func.type_set)) | ||
1969 | return; | ||
1970 | |||
1971 | /* VARIANT type will only work if the map only contains EET_G_*, but not UNION, VARIANT and ARRAY. */ | ||
1972 | if (group_type == EET_G_VARIANT) | ||
1973 | { | ||
1974 | int i; | ||
1975 | |||
1976 | for (i = 0; i < subtype->elements.num; ++i) | ||
1977 | if (subtype->elements.set[i].type != EET_T_UNKNOW | ||
1978 | && subtype->elements.set[i].group_type > EET_G_VAR_ARRAY | ||
1979 | && subtype->elements.set[i].group_type < EET_G_UNION) | ||
1980 | return; | ||
1981 | |||
1982 | subtype->unified_type = EINA_TRUE; | ||
1983 | } | ||
1984 | |||
1985 | if (subtype | ||
1986 | && subtype->unified_type | ||
1987 | && (type != EET_T_UNKNOW | ||
1988 | || group_type < EET_G_UNION)) | ||
1989 | return; | ||
1990 | |||
1991 | /* Sanity check done, let allocate ! */ | ||
1992 | edd->elements.num++; | ||
1993 | tmp = realloc(edd->elements.set, edd->elements.num * sizeof(Eet_Data_Element)); | ||
1994 | if (!tmp) | ||
1995 | return; | ||
1996 | |||
1997 | edd->elements.set = tmp; | ||
1998 | ede = &(edd->elements.set[edd->elements.num - 1]); | ||
1999 | ede->name = name; | ||
2000 | ede->directory_name_ptr = NULL; | ||
2001 | |||
2002 | /* | ||
2003 | * We do a special case when we do list,hash or whatever group of simple type. | ||
2004 | * Instead of handling it in encode/decode/dump/undump, we create an | ||
2005 | * implicit structure with only the simple type. | ||
2006 | */ | ||
2007 | if ((group_type > EET_G_UNKNOWN) | ||
2008 | && (group_type < EET_G_LAST) | ||
2009 | && (((type > EET_T_UNKNOW) && (type < EET_T_STRING)) | ||
2010 | || ((type > EET_T_NULL) && (type < EET_T_LAST))) | ||
2011 | && (!subtype)) | ||
2012 | { | ||
2013 | subtype = calloc(1, sizeof (Eet_Data_Descriptor)); | ||
2014 | if (!subtype) | ||
2015 | return; | ||
2016 | |||
2017 | subtype->name = "implicit"; | ||
2018 | subtype->size = eet_basic_codec[type - 1].size; | ||
2019 | memcpy(&subtype->func, &edd->func, sizeof(subtype->func)); | ||
2020 | |||
2021 | eet_data_descriptor_element_add(subtype, | ||
2022 | eet_basic_codec[type - 1].name, | ||
2023 | type, | ||
2024 | EET_G_UNKNOWN, | ||
2025 | 0, | ||
2026 | 0, | ||
2027 | /* 0, */ NULL, | ||
2028 | NULL); | ||
2029 | type = EET_T_UNKNOW; | ||
2030 | } | ||
2031 | |||
2032 | ede->type = type; | ||
2033 | ede->group_type = group_type; | ||
2034 | ede->offset = offset; | ||
2035 | ede->count = count; | ||
2036 | /* FIXME: For the time being, VAR_ARRAY, UNION and VARIANT will put the counter_offset in count. */ | ||
2037 | ede->counter_offset = count; | ||
2038 | /* ede->counter_offset = counter_offset; */ | ||
2039 | ede->counter_name = counter_name; | ||
2040 | |||
2041 | ede->subtype = subtype; | ||
2042 | } /* eet_data_descriptor_element_add */ | ||
2043 | |||
2044 | EAPI void * | ||
2045 | eet_data_read_cipher(Eet_File *ef, | ||
2046 | Eet_Data_Descriptor *edd, | ||
2047 | const char *name, | ||
2048 | const char *cipher_key) | ||
2049 | { | ||
2050 | const Eet_Dictionary *ed = NULL; | ||
2051 | const void *data = NULL; | ||
2052 | void *data_dec; | ||
2053 | Eet_Free_Context context; | ||
2054 | int required_free = 0; | ||
2055 | int size; | ||
2056 | |||
2057 | ed = eet_dictionary_get(ef); | ||
2058 | |||
2059 | if (!cipher_key) | ||
2060 | data = eet_read_direct(ef, name, &size); | ||
2061 | |||
2062 | if (!data) | ||
2063 | { | ||
2064 | required_free = 1; | ||
2065 | data = eet_read_cipher(ef, name, &size, cipher_key); | ||
2066 | if (!data) | ||
2067 | return NULL; | ||
2068 | } | ||
2069 | |||
2070 | eet_free_context_init(&context); | ||
2071 | data_dec = _eet_data_descriptor_decode(&context, ed, edd, data, size, NULL, 0); | ||
2072 | eet_free_context_shutdown(&context); | ||
2073 | |||
2074 | if (required_free) | ||
2075 | free((void *)data); | ||
2076 | |||
2077 | return data_dec; | ||
2078 | } /* eet_data_read_cipher */ | ||
2079 | |||
2080 | EAPI Eet_Node * | ||
2081 | eet_data_node_read_cipher(Eet_File *ef, | ||
2082 | const char *name, | ||
2083 | const char *cipher_key) | ||
2084 | { | ||
2085 | const Eet_Dictionary *ed = NULL; | ||
2086 | const void *data = NULL; | ||
2087 | Eet_Node *result; | ||
2088 | Eet_Free_Context context; | ||
2089 | int required_free = 0; | ||
2090 | int size; | ||
2091 | |||
2092 | ed = eet_dictionary_get(ef); | ||
2093 | |||
2094 | if (!cipher_key) | ||
2095 | data = eet_read_direct(ef, name, &size); | ||
2096 | |||
2097 | if (!data) | ||
2098 | { | ||
2099 | required_free = 1; | ||
2100 | data = eet_read_cipher(ef, name, &size, cipher_key); | ||
2101 | if (!data) | ||
2102 | return NULL; | ||
2103 | } | ||
2104 | |||
2105 | eet_free_context_init(&context); | ||
2106 | result = _eet_data_descriptor_decode(&context, ed, NULL, data, size, NULL, 0); | ||
2107 | eet_free_context_shutdown(&context); | ||
2108 | |||
2109 | if (required_free) | ||
2110 | free((void *)data); | ||
2111 | |||
2112 | return result; | ||
2113 | } /* eet_data_node_read_cipher */ | ||
2114 | |||
2115 | EAPI void * | ||
2116 | eet_data_read(Eet_File *ef, | ||
2117 | Eet_Data_Descriptor *edd, | ||
2118 | const char *name) | ||
2119 | { | ||
2120 | return eet_data_read_cipher(ef, edd, name, NULL); | ||
2121 | } /* eet_data_read */ | ||
2122 | |||
2123 | EAPI int | ||
2124 | eet_data_write_cipher(Eet_File *ef, | ||
2125 | Eet_Data_Descriptor *edd, | ||
2126 | const char *name, | ||
2127 | const char *cipher_key, | ||
2128 | const void *data, | ||
2129 | int compress) | ||
2130 | { | ||
2131 | Eet_Dictionary *ed; | ||
2132 | void *data_enc; | ||
2133 | int size; | ||
2134 | int val; | ||
2135 | |||
2136 | ed = eet_dictionary_get(ef); | ||
2137 | |||
2138 | data_enc = _eet_data_descriptor_encode(ed, edd, data, &size); | ||
2139 | if (!data_enc) | ||
2140 | return 0; | ||
2141 | |||
2142 | val = eet_write_cipher(ef, name, data_enc, size, compress, cipher_key); | ||
2143 | free(data_enc); | ||
2144 | return val; | ||
2145 | } /* eet_data_write_cipher */ | ||
2146 | |||
2147 | EAPI int | ||
2148 | eet_data_write(Eet_File *ef, | ||
2149 | Eet_Data_Descriptor *edd, | ||
2150 | const char *name, | ||
2151 | const void *data, | ||
2152 | int compress) | ||
2153 | { | ||
2154 | return eet_data_write_cipher(ef, edd, name, NULL, data, compress); | ||
2155 | } /* eet_data_write */ | ||
2156 | |||
2157 | static void | ||
2158 | eet_free_context_init(Eet_Free_Context *context) | ||
2159 | { | ||
2160 | unsigned int i = 0; | ||
2161 | |||
2162 | memset(context, 0, sizeof (Eet_Free_Context)); | ||
2163 | for (i = 0; i < EET_FREE_COUNT; ++i) | ||
2164 | { | ||
2165 | eina_array_step_set(&context->freelist.list[i], | ||
2166 | sizeof (context->freelist.list[i]), | ||
2167 | 32); | ||
2168 | eina_array_step_set(&context->freelist_array.list[i], | ||
2169 | sizeof (context->freelist.list[i]), | ||
2170 | 32); | ||
2171 | eina_array_step_set(&context->freelist_list.list[i], | ||
2172 | sizeof (context->freelist.list[i]), | ||
2173 | 32); | ||
2174 | eina_array_step_set(&context->freelist_hash.list[i], | ||
2175 | sizeof (context->freelist.list[i]), | ||
2176 | 32); | ||
2177 | eina_array_step_set(&context->freelist_str.list[i], | ||
2178 | sizeof (context->freelist.list[i]), | ||
2179 | 32); | ||
2180 | eina_array_step_set(&context->freelist_direct_str.list[i], | ||
2181 | sizeof (context->freelist.list[i]), | ||
2182 | 32); | ||
2183 | } | ||
2184 | } | ||
2185 | |||
2186 | static void | ||
2187 | eet_free_context_shutdown(Eet_Free_Context *context) | ||
2188 | { | ||
2189 | unsigned int i = 0; | ||
2190 | |||
2191 | for (i = 0; i < EET_FREE_COUNT; ++i) | ||
2192 | { | ||
2193 | eina_array_flush(&context->freelist.list[i]); | ||
2194 | eina_array_flush(&context->freelist_array.list[i]); | ||
2195 | eina_array_flush(&context->freelist_list.list[i]); | ||
2196 | eina_array_flush(&context->freelist_hash.list[i]); | ||
2197 | eina_array_flush(&context->freelist_str.list[i]); | ||
2198 | eina_array_flush(&context->freelist_direct_str.list[i]); | ||
2199 | } | ||
2200 | } | ||
2201 | |||
2202 | static int | ||
2203 | _eet_free_hash(void *data) | ||
2204 | { | ||
2205 | #ifdef _WIN64 | ||
2206 | __int64 ptr = (UINT_PTR)data; | ||
2207 | #else /* ifdef _WIN64 */ | ||
2208 | unsigned long ptr = (unsigned long)(data); | ||
2209 | #endif /* ifdef _WIN64 */ | ||
2210 | int hash; | ||
2211 | |||
2212 | hash = ptr; | ||
2213 | hash ^= ptr >> 8; | ||
2214 | hash ^= ptr >> 16; | ||
2215 | hash ^= ptr >> 24; | ||
2216 | |||
2217 | #if defined (_WIN64) || ((!defined (_WIN32)) && (LONG_BIT != 32)) | ||
2218 | hash ^= ptr >> 32; | ||
2219 | hash ^= ptr >> 40; | ||
2220 | hash ^= ptr >> 48; | ||
2221 | hash ^= ptr >> 56; | ||
2222 | #endif /* if defined (_WIN64) || ((!defined (_WIN32)) && (LONG_BIT != 32)) */ | ||
2223 | |||
2224 | return hash & 0xFF; | ||
2225 | } /* _eet_free_hash */ | ||
2226 | |||
2227 | static void | ||
2228 | _eet_free_add(Eet_Free *ef, | ||
2229 | void *data) | ||
2230 | { | ||
2231 | void *track; | ||
2232 | Eina_Array_Iterator it; | ||
2233 | unsigned int i; | ||
2234 | int hash; | ||
2235 | |||
2236 | hash = _eet_free_hash(data); | ||
2237 | |||
2238 | EINA_ARRAY_ITER_NEXT(&ef->list[hash], i, track, it) | ||
2239 | if (track == data) | ||
2240 | return; | ||
2241 | |||
2242 | eina_array_push(&ef->list[hash], data); | ||
2243 | } /* _eet_free_add */ | ||
2244 | |||
2245 | #if 0 | ||
2246 | static void | ||
2247 | _eet_free_del(Eet_Free *ef, | ||
2248 | void *data) | ||
2249 | { | ||
2250 | void *track; | ||
2251 | Eina_Array_Iterator it; | ||
2252 | unsigned int i; | ||
2253 | int hash; | ||
2254 | |||
2255 | hash = _eet_free_hash(data); | ||
2256 | |||
2257 | EINA_ARRAY_ITER_NEXT(&ef->list[hash], i, track, it) | ||
2258 | if (track == data) | ||
2259 | { | ||
2260 | eina_array_data_set(&ef->list[hash], i, NULL); | ||
2261 | return; | ||
2262 | } | ||
2263 | } | ||
2264 | |||
2265 | #endif | ||
2266 | |||
2267 | static void | ||
2268 | _eet_free_reset(Eet_Free *ef) | ||
2269 | { | ||
2270 | unsigned int i; | ||
2271 | |||
2272 | if (ef->ref > 0) | ||
2273 | return; | ||
2274 | |||
2275 | for (i = 0; i < EET_FREE_COUNT; ++i) | ||
2276 | eina_array_clean(&ef->list[i]); | ||
2277 | } /* _eet_free_reset */ | ||
2278 | |||
2279 | static void | ||
2280 | _eet_free_ref(Eet_Free *ef) | ||
2281 | { | ||
2282 | ef->ref++; | ||
2283 | } /* _eet_free_ref */ | ||
2284 | |||
2285 | static void | ||
2286 | _eet_free_unref(Eet_Free *ef) | ||
2287 | { | ||
2288 | ef->ref--; | ||
2289 | } /* _eet_free_unref */ | ||
2290 | |||
2291 | #define _eet_freelist_add(Ctx, Data) _eet_free_add(&Ctx->freelist, Data); | ||
2292 | #define _eet_freelist_del(Ctx, Data) _eet_free_del(&Ctx->freelist, Data); | ||
2293 | #define _eet_freelist_reset(Ctx) _eet_free_reset(&Ctx->freelist); | ||
2294 | #define _eet_freelist_ref(Ctx) _eet_free_ref(&Ctx->freelist); | ||
2295 | #define _eet_freelist_unref(Ctx) _eet_free_unref(&Ctx->freelist); | ||
2296 | |||
2297 | static void | ||
2298 | _eet_freelist_free(Eet_Free_Context *context, | ||
2299 | Eet_Data_Descriptor *edd) | ||
2300 | { | ||
2301 | void *track; | ||
2302 | Eina_Array_Iterator it; | ||
2303 | unsigned int j; | ||
2304 | unsigned int i; | ||
2305 | |||
2306 | if (context->freelist.ref > 0) | ||
2307 | return; | ||
2308 | |||
2309 | for (j = 0; j < EET_FREE_COUNT; ++j) | ||
2310 | EINA_ARRAY_ITER_NEXT(&context->freelist.list[j], i, track, it) | ||
2311 | if (track) | ||
2312 | { | ||
2313 | if (edd) | ||
2314 | edd->func.mem_free(track); | ||
2315 | else | ||
2316 | free(track); | ||
2317 | } | ||
2318 | _eet_free_reset(&context->freelist); | ||
2319 | } /* _eet_freelist_free */ | ||
2320 | |||
2321 | #define _eet_freelist_array_add(Ctx, Data) _eet_free_add(&Ctx->freelist_array, Data); | ||
2322 | #define _eet_freelist_array_del(Ctx, Data) _eet_free_del(&Ctx->freelist_array, Data); | ||
2323 | #define _eet_freelist_array_reset(Ctx) _eet_free_reset(&Ctx->freelist_array); | ||
2324 | #define _eet_freelist_array_ref(Ctx) _eet_free_ref(&Ctx->freelist_array); | ||
2325 | #define _eet_freelist_array_unref(Ctx) _eet_free_unref(&Ctx->freelist_array); | ||
2326 | |||
2327 | static void | ||
2328 | _eet_freelist_array_free(Eet_Free_Context *context, | ||
2329 | Eet_Data_Descriptor *edd) | ||
2330 | { | ||
2331 | void *track; | ||
2332 | Eina_Array_Iterator it; | ||
2333 | unsigned int j; | ||
2334 | unsigned int i; | ||
2335 | |||
2336 | if (context->freelist_array.ref > 0) | ||
2337 | return; | ||
2338 | |||
2339 | for (j = 0; j < EET_FREE_COUNT; ++j) | ||
2340 | EINA_ARRAY_ITER_NEXT(&context->freelist_array.list[j], i, track, it) | ||
2341 | if (track) | ||
2342 | { | ||
2343 | if (edd) | ||
2344 | { | ||
2345 | if (edd->func.array_free) | ||
2346 | edd->func.array_free(track); | ||
2347 | else | ||
2348 | edd->func.mem_free(track); | ||
2349 | } | ||
2350 | else | ||
2351 | free(track); | ||
2352 | } | ||
2353 | _eet_free_reset(&context->freelist_array); | ||
2354 | } /* _eet_freelist_array_free */ | ||
2355 | |||
2356 | #define _eet_freelist_list_add(Ctx, Data) _eet_free_add(&Ctx->freelist_list, Data); | ||
2357 | #define _eet_freelist_list_del(Ctx, Data) _eet_free_del(&Ctx->freelist_list, Data); | ||
2358 | #define _eet_freelist_list_reset(Ctx) _eet_free_reset(&Ctx->freelist_list); | ||
2359 | #define _eet_freelist_list_ref(Ctx) _eet_free_ref(&Ctx->freelist_list); | ||
2360 | #define _eet_freelist_list_unref(Ctx) _eet_free_unref(&Ctx->freelist_list); | ||
2361 | |||
2362 | static void | ||
2363 | _eet_freelist_list_free(Eet_Free_Context *context, | ||
2364 | Eet_Data_Descriptor *edd) | ||
2365 | { | ||
2366 | void *track; | ||
2367 | Eina_Array_Iterator it; | ||
2368 | unsigned int j; | ||
2369 | unsigned int i; | ||
2370 | |||
2371 | if (context->freelist_list.ref > 0) | ||
2372 | return; | ||
2373 | |||
2374 | for (j = 0; j < EET_FREE_COUNT; ++j) | ||
2375 | EINA_ARRAY_ITER_NEXT(&context->freelist_list.list[j], i, track, it) | ||
2376 | if (track) | ||
2377 | { | ||
2378 | if (edd) | ||
2379 | edd->func.list_free(*((void **)(track))); | ||
2380 | } | ||
2381 | _eet_free_reset(&context->freelist_list); | ||
2382 | } /* _eet_freelist_list_free */ | ||
2383 | |||
2384 | #define _eet_freelist_str_add(Ctx, Data) _eet_free_add(&Ctx->freelist_str, Data); | ||
2385 | #define _eet_freelist_str_del(Ctx, Data) _eet_free_del(&Ctx->freelist_str, Data); | ||
2386 | #define _eet_freelist_str_reset(Ctx) _eet_free_reset(&Ctx->freelist_str); | ||
2387 | #define _eet_freelist_str_ref(Ctx) _eet_free_ref(&Ctx->freelist_str); | ||
2388 | #define _eet_freelist_str_unref(Ctx) _eet_free_unref(&Ctx->freelist_str); | ||
2389 | |||
2390 | static void | ||
2391 | _eet_freelist_str_free(Eet_Free_Context *context, | ||
2392 | Eet_Data_Descriptor *edd) | ||
2393 | { | ||
2394 | void *track; | ||
2395 | Eina_Array_Iterator it; | ||
2396 | unsigned int j; | ||
2397 | unsigned int i; | ||
2398 | |||
2399 | if (context->freelist_str.ref > 0) | ||
2400 | return; | ||
2401 | |||
2402 | for (j = 0; j < EET_FREE_COUNT; ++j) | ||
2403 | EINA_ARRAY_ITER_NEXT(&context->freelist_str.list[j], i, track, it) | ||
2404 | if (track) | ||
2405 | { | ||
2406 | if (edd) | ||
2407 | edd->func.str_free(track); | ||
2408 | else | ||
2409 | free(track); | ||
2410 | } | ||
2411 | _eet_free_reset(&context->freelist_str); | ||
2412 | } /* _eet_freelist_str_free */ | ||
2413 | |||
2414 | #define _eet_freelist_direct_str_add(Ctx, Data) _eet_free_add(&Ctx->freelist_direct_str, Data); | ||
2415 | #define _eet_freelist_direct_str_del(Ctx, Data) _eet_free_del(&Ctx->freelist_direct_str, Data); | ||
2416 | #define _eet_freelist_direct_str_reset(Ctx) _eet_free_reset(&Ctx->freelist_direct_str); | ||
2417 | #define _eet_freelist_direct_str_ref(Ctx) _eet_free_ref(&Ctx->freelist_direct_str); | ||
2418 | #define _eet_freelist_direct_str_unref(Ctx) _eet_free_unref(&Ctx->freelist_direct_str); | ||
2419 | |||
2420 | static void | ||
2421 | _eet_freelist_direct_str_free(Eet_Free_Context *context, | ||
2422 | Eet_Data_Descriptor *edd) | ||
2423 | { | ||
2424 | void *track; | ||
2425 | Eina_Array_Iterator it; | ||
2426 | unsigned int j; | ||
2427 | unsigned int i; | ||
2428 | |||
2429 | if (context->freelist_direct_str.ref > 0) | ||
2430 | return; | ||
2431 | |||
2432 | for (j = 0; j < EET_FREE_COUNT; ++j) | ||
2433 | EINA_ARRAY_ITER_NEXT(&context->freelist_str.list[j], i, track, it) | ||
2434 | if (track) | ||
2435 | { | ||
2436 | if (edd) | ||
2437 | edd->func.str_direct_free(track); | ||
2438 | else | ||
2439 | free(track); | ||
2440 | } | ||
2441 | _eet_free_reset(&context->freelist_direct_str); | ||
2442 | } /* _eet_freelist_direct_str_free */ | ||
2443 | |||
2444 | #define _eet_freelist_hash_add(Ctx, Data) _eet_free_add(&Ctx->freelist_hash, Data); | ||
2445 | #define _eet_freelist_hash_del(Ctx, Data) _eet_free_del(&Ctx->freelist_hash, Data); | ||
2446 | #define _eet_freelist_hash_reset(Ctx) _eet_free_reset(&Ctx->freelist_hash); | ||
2447 | #define _eet_freelist_hash_ref(Ctx) _eet_free_ref(&Ctx->freelist_hash); | ||
2448 | #define _eet_freelist_hash_unref(Ctx) _eet_free_unref(&Ctx->freelist_hash); | ||
2449 | |||
2450 | static void | ||
2451 | _eet_freelist_hash_free(Eet_Free_Context *context, | ||
2452 | Eet_Data_Descriptor *edd) | ||
2453 | { | ||
2454 | void *track; | ||
2455 | Eina_Array_Iterator it; | ||
2456 | unsigned int j; | ||
2457 | unsigned int i; | ||
2458 | |||
2459 | if (context->freelist_hash.ref > 0) | ||
2460 | return; | ||
2461 | |||
2462 | for (j = 0; j < EET_FREE_COUNT; ++j) | ||
2463 | EINA_ARRAY_ITER_NEXT(&context->freelist_hash.list[j], i, track, it) | ||
2464 | if (track) | ||
2465 | { | ||
2466 | if (edd) | ||
2467 | edd->func.hash_free(track); | ||
2468 | else | ||
2469 | free(track); | ||
2470 | } | ||
2471 | _eet_free_reset(&context->freelist_hash); | ||
2472 | } /* _eet_freelist_hash_free */ | ||
2473 | |||
2474 | static void | ||
2475 | _eet_freelist_all_ref(Eet_Free_Context *freelist_context) | ||
2476 | { | ||
2477 | _eet_freelist_ref(freelist_context); | ||
2478 | _eet_freelist_str_ref(freelist_context); | ||
2479 | _eet_freelist_list_ref(freelist_context); | ||
2480 | _eet_freelist_hash_ref(freelist_context); | ||
2481 | _eet_freelist_direct_str_ref(freelist_context); | ||
2482 | } /* _eet_freelist_all_ref */ | ||
2483 | |||
2484 | static void | ||
2485 | _eet_freelist_all_unref(Eet_Free_Context *freelist_context) | ||
2486 | { | ||
2487 | _eet_freelist_unref(freelist_context); | ||
2488 | _eet_freelist_str_unref(freelist_context); | ||
2489 | _eet_freelist_list_unref(freelist_context); | ||
2490 | _eet_freelist_hash_unref(freelist_context); | ||
2491 | _eet_freelist_direct_str_unref(freelist_context); | ||
2492 | } /* _eet_freelist_all_unref */ | ||
2493 | |||
2494 | static int | ||
2495 | eet_data_descriptor_encode_hash_cb(void *hash __UNUSED__, | ||
2496 | const char *cipher_key, | ||
2497 | void *hdata, | ||
2498 | void *fdata) | ||
2499 | { | ||
2500 | Eet_Dictionary *ed; | ||
2501 | Eet_Data_Encode_Hash_Info *edehi; | ||
2502 | Eet_Data_Stream *ds; | ||
2503 | Eet_Data_Element *ede; | ||
2504 | Eet_Data_Chunk *echnk; | ||
2505 | void *data = NULL; | ||
2506 | int size; | ||
2507 | |||
2508 | edehi = fdata; | ||
2509 | ede = edehi->ede; | ||
2510 | ds = edehi->ds; | ||
2511 | ed = edehi->ed; | ||
2512 | |||
2513 | /* Store key */ | ||
2514 | data = eet_data_put_type(ed, | ||
2515 | EET_T_STRING, | ||
2516 | &cipher_key, | ||
2517 | &size); | ||
2518 | if (data) | ||
2519 | { | ||
2520 | echnk = eet_data_chunk_new(data, | ||
2521 | size, | ||
2522 | ede->name, | ||
2523 | ede->type, | ||
2524 | ede->group_type); | ||
2525 | eet_data_chunk_put(ed, echnk, ds); | ||
2526 | eet_data_chunk_free(echnk); | ||
2527 | free(data); | ||
2528 | data = NULL; | ||
2529 | } | ||
2530 | |||
2531 | EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)), return ); | ||
2532 | |||
2533 | /* Store data */ | ||
2534 | if (ede->type >= EET_T_STRING) | ||
2535 | eet_data_put_unknown(ed, NULL, ede, ds, &hdata); | ||
2536 | else | ||
2537 | { | ||
2538 | if (ede->subtype) | ||
2539 | data = _eet_data_descriptor_encode(ed, | ||
2540 | ede->subtype, | ||
2541 | hdata, | ||
2542 | &size); | ||
2543 | |||
2544 | if (data) | ||
2545 | { | ||
2546 | echnk = eet_data_chunk_new(data, | ||
2547 | size, | ||
2548 | ede->name, | ||
2549 | ede->type, | ||
2550 | ede->group_type); | ||
2551 | eet_data_chunk_put(ed, echnk, ds); | ||
2552 | eet_data_chunk_free(echnk); | ||
2553 | free(data); | ||
2554 | data = NULL; | ||
2555 | } | ||
2556 | } | ||
2557 | |||
2558 | return 1; | ||
2559 | } /* eet_data_descriptor_encode_hash_cb */ | ||
2560 | |||
2561 | static char * | ||
2562 | _eet_data_dump_token_get(const char *src, | ||
2563 | int *len) | ||
2564 | { | ||
2565 | const char *p; | ||
2566 | char *tok = NULL; | ||
2567 | int in_token = 0; | ||
2568 | int in_quote = 0; | ||
2569 | int tlen = 0, tsize = 0; | ||
2570 | |||
2571 | #define TOK_ADD(x) \ | ||
2572 | do { \ | ||
2573 | tlen++; \ | ||
2574 | if (tlen >= tsize) \ | ||
2575 | { \ | ||
2576 | tsize += 32; \ | ||
2577 | tok = realloc(tok, tsize); \ | ||
2578 | } \ | ||
2579 | tok[tlen - 1] = x; \ | ||
2580 | } while (0) | ||
2581 | |||
2582 | for (p = src; *len > 0; p++, (*len)--) | ||
2583 | { | ||
2584 | if (in_token) | ||
2585 | { | ||
2586 | if (in_quote) | ||
2587 | { | ||
2588 | if ((p[0] == '\"') && (p > src) && (p[-1] != '\\')) | ||
2589 | in_quote = 0; | ||
2590 | else if ((p[0] == '\\') && (*len > 1) && | ||
2591 | (p[1] == '\"')) | ||
2592 | { | ||
2593 | /* skip */ | ||
2594 | } | ||
2595 | else if ((p[0] == '\\') && (p > src) && (p[-1] == '\\')) | ||
2596 | { | ||
2597 | /* skip */ | ||
2598 | } | ||
2599 | else if ((p[0] == '\\') && (*len > 1) && (p[1] == 'n')) | ||
2600 | { | ||
2601 | /* skip */ | ||
2602 | } | ||
2603 | else if ((p[0] == 'n') && (p > src) && (p[-1] == '\\')) | ||
2604 | TOK_ADD('\n'); | ||
2605 | else | ||
2606 | TOK_ADD(p[0]); | ||
2607 | } | ||
2608 | else | ||
2609 | { | ||
2610 | if (p[0] == '\"') | ||
2611 | in_quote = 1; | ||
2612 | else | ||
2613 | { | ||
2614 | if ((isspace(p[0])) || (p[0] == ';')) /* token ends here */ | ||
2615 | { | ||
2616 | TOK_ADD(0); | ||
2617 | (*len)--; | ||
2618 | return tok; | ||
2619 | } | ||
2620 | else | ||
2621 | TOK_ADD(p[0]); | ||
2622 | } | ||
2623 | } | ||
2624 | } | ||
2625 | else if (!((isspace(p[0])) || (p[0] == ';'))) | ||
2626 | { | ||
2627 | in_token = 1; | ||
2628 | (*len)++; | ||
2629 | p--; | ||
2630 | } | ||
2631 | } | ||
2632 | if (in_token) | ||
2633 | { | ||
2634 | TOK_ADD(0); | ||
2635 | return tok; | ||
2636 | } | ||
2637 | |||
2638 | if (tok) | ||
2639 | free(tok); | ||
2640 | |||
2641 | return NULL; | ||
2642 | } /* _eet_data_dump_token_get */ | ||
2643 | |||
2644 | static void | ||
2645 | eet_data_encode(Eet_Dictionary *ed, | ||
2646 | Eet_Data_Stream *ds, | ||
2647 | void *data, | ||
2648 | const char *name, | ||
2649 | int size, | ||
2650 | int type, | ||
2651 | int group_type) | ||
2652 | { | ||
2653 | Eet_Data_Chunk *echnk; | ||
2654 | |||
2655 | if (!data) | ||
2656 | type = EET_T_NULL; | ||
2657 | |||
2658 | if (group_type != EET_G_UNKNOWN) | ||
2659 | if (type >= EET_T_LAST) | ||
2660 | type = EET_T_UNKNOW; | ||
2661 | |||
2662 | echnk = eet_data_chunk_new(data, size, name, type, group_type); | ||
2663 | eet_data_chunk_put(ed, echnk, ds); | ||
2664 | eet_data_chunk_free(echnk); | ||
2665 | free(data); | ||
2666 | } /* eet_data_encode */ | ||
2667 | |||
2668 | static void * | ||
2669 | _eet_data_dump_encode(int parent_type, | ||
2670 | Eet_Dictionary *ed, | ||
2671 | Eet_Node *node, | ||
2672 | int *size_ret) | ||
2673 | { | ||
2674 | Eet_Data_Chunk *chnk = NULL; | ||
2675 | Eet_Data_Stream *ds; | ||
2676 | void *cdata, *data; | ||
2677 | int csize, size; | ||
2678 | int count; | ||
2679 | int child_type; | ||
2680 | Eet_Node *n; | ||
2681 | |||
2682 | if (_eet_data_words_bigendian == -1) | ||
2683 | { | ||
2684 | unsigned long int v; | ||
2685 | |||
2686 | v = htonl(0x12345678); | ||
2687 | if (v == 0x12345678) | ||
2688 | _eet_data_words_bigendian = 1; | ||
2689 | else | ||
2690 | _eet_data_words_bigendian = 0; | ||
2691 | } | ||
2692 | |||
2693 | if (!node) | ||
2694 | return NULL; | ||
2695 | |||
2696 | ds = eet_data_stream_new(); | ||
2697 | if (!ds) | ||
2698 | return NULL; | ||
2699 | |||
2700 | switch (node->type) | ||
2701 | { | ||
2702 | case EET_G_UNKNOWN: | ||
2703 | for (n = node->values; n; n = n->next) | ||
2704 | { | ||
2705 | data = _eet_data_dump_encode(node->type, ed, n, &size); | ||
2706 | if (data) | ||
2707 | { | ||
2708 | eet_data_stream_write(ds, data, size); | ||
2709 | free(data); | ||
2710 | } | ||
2711 | } | ||
2712 | break; | ||
2713 | |||
2714 | case EET_G_ARRAY: | ||
2715 | case EET_G_VAR_ARRAY: | ||
2716 | for (child_type = EET_T_NULL, n = node->values; n; n = n->next) | ||
2717 | { | ||
2718 | if (n->type != EET_T_NULL) | ||
2719 | { | ||
2720 | child_type = n->type; | ||
2721 | break; | ||
2722 | } | ||
2723 | } | ||
2724 | |||
2725 | data = eet_data_put_type(ed, | ||
2726 | EET_T_INT, | ||
2727 | &node->count, | ||
2728 | &size); | ||
2729 | eet_data_encode(ed, | ||
2730 | ds, | ||
2731 | data, | ||
2732 | node->name, | ||
2733 | size, | ||
2734 | child_type, | ||
2735 | node->type); | ||
2736 | |||
2737 | count = node->count; | ||
2738 | |||
2739 | for (n = node->values; n; n = n->next) | ||
2740 | { | ||
2741 | int pos = ds->pos; | ||
2742 | |||
2743 | switch (n->type) | ||
2744 | { | ||
2745 | case EET_T_STRING: | ||
2746 | case EET_T_INLINED_STRING: | ||
2747 | data = eet_data_put_type(ed, | ||
2748 | n->type, | ||
2749 | &(n->data.value.str), | ||
2750 | &size); | ||
2751 | if (data) | ||
2752 | eet_data_encode(ed, | ||
2753 | ds, | ||
2754 | data, | ||
2755 | node->name, | ||
2756 | size, | ||
2757 | n->type, | ||
2758 | node->type); | ||
2759 | |||
2760 | break; | ||
2761 | |||
2762 | case EET_T_NULL: | ||
2763 | continue; | ||
2764 | |||
2765 | default: | ||
2766 | data = _eet_data_dump_encode(n->type, ed, n, &size); | ||
2767 | eet_data_encode(ed, | ||
2768 | ds, | ||
2769 | data, | ||
2770 | node->name, | ||
2771 | size, | ||
2772 | n->type, | ||
2773 | node->type); | ||
2774 | break; | ||
2775 | } /* switch */ | ||
2776 | if (ds->pos != pos) | ||
2777 | count--; | ||
2778 | } | ||
2779 | |||
2780 | for (; count; count--) | ||
2781 | { | ||
2782 | eet_data_encode(ed, | ||
2783 | ds, | ||
2784 | NULL, | ||
2785 | node->name, | ||
2786 | 0, | ||
2787 | EET_T_NULL, | ||
2788 | node->type); | ||
2789 | } | ||
2790 | |||
2791 | /* Array is somekind of special case, so we should embed it inside another chunk. */ | ||
2792 | *size_ret = ds->pos; | ||
2793 | cdata = ds->data; | ||
2794 | |||
2795 | ds->data = NULL; | ||
2796 | ds->size = 0; | ||
2797 | eet_data_stream_free(ds); | ||
2798 | |||
2799 | return cdata; | ||
2800 | break; | ||
2801 | |||
2802 | case EET_G_LIST: | ||
2803 | for (n = node->values; n; n = n->next) | ||
2804 | { | ||
2805 | switch (n->type) | ||
2806 | { | ||
2807 | case EET_T_STRING: | ||
2808 | case EET_T_INLINED_STRING: | ||
2809 | data = eet_data_put_type(ed, | ||
2810 | n->type, | ||
2811 | &(n->data.value.str), | ||
2812 | &size); | ||
2813 | if (data) | ||
2814 | eet_data_encode(ed, | ||
2815 | ds, | ||
2816 | data, | ||
2817 | node->name, | ||
2818 | size, | ||
2819 | n->type, | ||
2820 | node->type); | ||
2821 | |||
2822 | break; | ||
2823 | |||
2824 | case EET_T_NULL: | ||
2825 | continue; | ||
2826 | |||
2827 | default: | ||
2828 | data = _eet_data_dump_encode(node->type, ed, n, &size); | ||
2829 | eet_data_encode(ed, | ||
2830 | ds, | ||
2831 | data, | ||
2832 | node->name, | ||
2833 | size, | ||
2834 | n->type, | ||
2835 | node->type); | ||
2836 | } /* switch */ | ||
2837 | } | ||
2838 | |||
2839 | /* List is another somekind of special case, every chunk is embed inside a list chunk. */ | ||
2840 | *size_ret = ds->pos; | ||
2841 | cdata = ds->data; | ||
2842 | |||
2843 | ds->data = NULL; | ||
2844 | ds->size = 0; | ||
2845 | eet_data_stream_free(ds); | ||
2846 | |||
2847 | return cdata; | ||
2848 | break; | ||
2849 | |||
2850 | case EET_G_HASH: | ||
2851 | if (node->key) | ||
2852 | { | ||
2853 | data = eet_data_put_type(ed, | ||
2854 | EET_T_STRING, | ||
2855 | &node->key, | ||
2856 | &size); | ||
2857 | eet_data_encode(ed, | ||
2858 | ds, | ||
2859 | data, | ||
2860 | node->name, | ||
2861 | size, | ||
2862 | node->type, | ||
2863 | node->type); | ||
2864 | } | ||
2865 | else | ||
2866 | /* A Hash without key will not decode correctly. */ | ||
2867 | return NULL; | ||
2868 | |||
2869 | for (n = node->values; n; n = n->next) | ||
2870 | { | ||
2871 | switch (n->type) | ||
2872 | { | ||
2873 | case EET_T_STRING: | ||
2874 | case EET_T_INLINED_STRING: | ||
2875 | data = eet_data_put_type(ed, | ||
2876 | n->type, | ||
2877 | &(n->data.value.str), | ||
2878 | &size); | ||
2879 | if (data) | ||
2880 | eet_data_encode(ed, | ||
2881 | ds, | ||
2882 | data, | ||
2883 | node->name, | ||
2884 | size, | ||
2885 | n->type, | ||
2886 | node->type); | ||
2887 | |||
2888 | break; | ||
2889 | |||
2890 | case EET_T_NULL: | ||
2891 | continue; | ||
2892 | |||
2893 | default: | ||
2894 | data = _eet_data_dump_encode(node->type, ed, n, &size); | ||
2895 | eet_data_encode(ed, | ||
2896 | ds, | ||
2897 | data, | ||
2898 | node->name, | ||
2899 | size, | ||
2900 | n->type, | ||
2901 | node->type); | ||
2902 | } /* switch */ | ||
2903 | } | ||
2904 | |||
2905 | /* Hash is somekind of special case, so we should embed it inside another chunk. */ | ||
2906 | *size_ret = ds->pos; | ||
2907 | cdata = ds->data; | ||
2908 | |||
2909 | eet_data_stream_flush(ds); | ||
2910 | |||
2911 | return cdata; | ||
2912 | |||
2913 | case EET_T_NULL: | ||
2914 | break; | ||
2915 | |||
2916 | #define EET_DATA_NODE_ENCODE(Eet_Type, Type) \ | ||
2917 | case Eet_Type: \ | ||
2918 | data = eet_data_put_type(ed, node->type, &(node->data.value.Type), &size); \ | ||
2919 | if (data) \ | ||
2920 | { \ | ||
2921 | eet_data_encode(ed, \ | ||
2922 | ds, \ | ||
2923 | data, \ | ||
2924 | node->name, \ | ||
2925 | size, \ | ||
2926 | node->type, \ | ||
2927 | parent_type); \ | ||
2928 | cdata = ds->data; \ | ||
2929 | *size_ret = ds->pos; \ | ||
2930 | eet_data_stream_flush(ds); \ | ||
2931 | return cdata; \ | ||
2932 | } /* switch */ \ | ||
2933 | break; | ||
2934 | |||
2935 | EET_DATA_NODE_ENCODE(EET_T_CHAR, c); | ||
2936 | EET_DATA_NODE_ENCODE(EET_T_SHORT, s); | ||
2937 | EET_DATA_NODE_ENCODE(EET_T_INT, i); | ||
2938 | EET_DATA_NODE_ENCODE(EET_T_LONG_LONG, l); | ||
2939 | EET_DATA_NODE_ENCODE(EET_T_FLOAT, f); | ||
2940 | EET_DATA_NODE_ENCODE(EET_T_DOUBLE, d); | ||
2941 | EET_DATA_NODE_ENCODE(EET_T_UCHAR, uc); | ||
2942 | EET_DATA_NODE_ENCODE(EET_T_USHORT, us); | ||
2943 | EET_DATA_NODE_ENCODE(EET_T_UINT, ui); | ||
2944 | EET_DATA_NODE_ENCODE(EET_T_ULONG_LONG, ul); | ||
2945 | EET_DATA_NODE_ENCODE(EET_T_INLINED_STRING, str); | ||
2946 | EET_DATA_NODE_ENCODE(EET_T_STRING, str); | ||
2947 | |||
2948 | default: | ||
2949 | break; | ||
2950 | } | ||
2951 | |||
2952 | if ((node->type >= EET_G_UNKNOWN) && (node->type < EET_G_LAST)) | ||
2953 | chnk = eet_data_chunk_new(ds->data, | ||
2954 | ds->pos, | ||
2955 | node->name, | ||
2956 | EET_T_UNKNOW, | ||
2957 | node->type); | ||
2958 | else | ||
2959 | chnk = eet_data_chunk_new(ds->data, | ||
2960 | ds->pos, | ||
2961 | node->name, | ||
2962 | node->type, | ||
2963 | EET_G_UNKNOWN); | ||
2964 | |||
2965 | eet_data_stream_flush(ds); | ||
2966 | |||
2967 | ds = eet_data_stream_new(); | ||
2968 | eet_data_chunk_put(ed, chnk, ds); | ||
2969 | cdata = ds->data; | ||
2970 | csize = ds->pos; | ||
2971 | |||
2972 | eet_data_stream_flush(ds); | ||
2973 | *size_ret = csize; | ||
2974 | |||
2975 | free(chnk->data); | ||
2976 | eet_data_chunk_free(chnk); | ||
2977 | |||
2978 | return cdata; | ||
2979 | } /* _eet_data_dump_encode */ | ||
2980 | |||
2981 | static void * | ||
2982 | _eet_data_dump_parse(Eet_Dictionary *ed, | ||
2983 | int *size_ret, | ||
2984 | const char *src, | ||
2985 | int size) | ||
2986 | { | ||
2987 | void *cdata = NULL; | ||
2988 | const char *p = NULL; | ||
2989 | #define M_NONE 0 | ||
2990 | #define M_STRUCT 1 | ||
2991 | #define M_ 2 | ||
2992 | int left, jump; | ||
2993 | Eet_Node *node_base = NULL; | ||
2994 | Eet_Node *node = NULL; | ||
2995 | Eet_Node *n = NULL, *nn = NULL; | ||
2996 | |||
2997 | /* FIXME; handle parse errors */ | ||
2998 | #define TOK_GET(t) \ | ||
2999 | jump = left; t = _eet_data_dump_token_get(p, &left); p += jump - left; | ||
3000 | left = size; | ||
3001 | for (p = src; p < (src + size); ) | ||
3002 | { | ||
3003 | char *tok1, *tok2, *tok3, *tok4; | ||
3004 | |||
3005 | TOK_GET(tok1); | ||
3006 | if (tok1) | ||
3007 | { | ||
3008 | if (!strcmp(tok1, "group")) | ||
3009 | { | ||
3010 | TOK_GET(tok2); | ||
3011 | if (tok2) | ||
3012 | { | ||
3013 | TOK_GET(tok3); | ||
3014 | if (tok3) | ||
3015 | { | ||
3016 | TOK_GET(tok4); | ||
3017 | if (tok4) | ||
3018 | { | ||
3019 | if (!strcmp(tok4, "{")) | ||
3020 | { | ||
3021 | /* we have 'group NAM TYP {' */ | ||
3022 | n = eet_node_new(); | ||
3023 | if (n) | ||
3024 | { | ||
3025 | n->parent = node; | ||
3026 | if (!node_base) | ||
3027 | node_base = n; | ||
3028 | |||
3029 | if (node) | ||
3030 | { | ||
3031 | /* append node */ | ||
3032 | if (!node->values) | ||
3033 | node->values = n; | ||
3034 | else | ||
3035 | for (nn = node->values; nn; | ||
3036 | nn = nn->next) | ||
3037 | { | ||
3038 | if (!nn->next) | ||
3039 | { | ||
3040 | nn->next = n; | ||
3041 | break; | ||
3042 | } | ||
3043 | } | ||
3044 | } | ||
3045 | |||
3046 | n->name = eina_stringshare_add(tok2); | ||
3047 | if (!strcmp(tok3, "struct")) | ||
3048 | n->type = EET_G_UNKNOWN; | ||
3049 | else if (!strcmp(tok3, "array")) | ||
3050 | n->type = EET_G_ARRAY; | ||
3051 | else if (!strcmp(tok3, "var_array")) | ||
3052 | n->type = EET_G_VAR_ARRAY; | ||
3053 | else if (!strcmp(tok3, "list")) | ||
3054 | n->type = EET_G_LIST; | ||
3055 | else if (!strcmp(tok3, "hash")) | ||
3056 | n->type = EET_G_HASH; | ||
3057 | else | ||
3058 | ERR( | ||
3059 | "ERROR: group type '%s' invalid.", | ||
3060 | tok3); | ||
3061 | |||
3062 | node = n; | ||
3063 | } | ||
3064 | } | ||
3065 | |||
3066 | free(tok4); | ||
3067 | } | ||
3068 | |||
3069 | free(tok3); | ||
3070 | } | ||
3071 | |||
3072 | free(tok2); | ||
3073 | } | ||
3074 | } | ||
3075 | else if (!strcmp(tok1, "value")) | ||
3076 | { | ||
3077 | TOK_GET(tok2); | ||
3078 | if (tok2) | ||
3079 | { | ||
3080 | TOK_GET(tok3); | ||
3081 | if (tok3) | ||
3082 | { | ||
3083 | TOK_GET(tok4); | ||
3084 | if (tok4) | ||
3085 | { | ||
3086 | /* we have 'value NAME TYP XXX' */ | ||
3087 | if (node_base) | ||
3088 | { | ||
3089 | n = eet_node_new(); | ||
3090 | if (n) | ||
3091 | { | ||
3092 | n->parent = node; | ||
3093 | /* append node */ | ||
3094 | if (!node->values) | ||
3095 | node->values = n; | ||
3096 | else | ||
3097 | for (nn = node->values; nn; | ||
3098 | nn = nn->next) | ||
3099 | { | ||
3100 | if (!nn->next) | ||
3101 | { | ||
3102 | nn->next = n; | ||
3103 | break; | ||
3104 | } | ||
3105 | } | ||
3106 | |||
3107 | n->name = eina_stringshare_add(tok2); | ||
3108 | if (!strcmp(tok3, "char:")) | ||
3109 | { | ||
3110 | n->type = EET_T_CHAR; | ||
3111 | sscanf(tok4, FMT_CHAR, | ||
3112 | &(n->data.value.c)); | ||
3113 | } | ||
3114 | else if (!strcmp(tok3, "short:")) | ||
3115 | { | ||
3116 | n->type = EET_T_SHORT; | ||
3117 | sscanf(tok4, "%hi", | ||
3118 | &(n->data.value.s)); | ||
3119 | } | ||
3120 | else if (!strcmp(tok3, "int:")) | ||
3121 | { | ||
3122 | n->type = EET_T_INT; | ||
3123 | sscanf(tok4, "%i", | ||
3124 | &(n->data.value.i)); | ||
3125 | } | ||
3126 | else if (!strcmp(tok3, "long_long:")) | ||
3127 | { | ||
3128 | n->type = EET_T_LONG_LONG; | ||
3129 | sscanf(tok4, FMT_LONG_LONG, | ||
3130 | &(n->data.value.l)); | ||
3131 | } | ||
3132 | else if (!strcmp(tok3, "float:")) | ||
3133 | { | ||
3134 | n->type = EET_T_FLOAT; | ||
3135 | sscanf(tok4, "%f", | ||
3136 | &(n->data.value.f)); | ||
3137 | } | ||
3138 | else if (!strcmp(tok3, "double:")) | ||
3139 | { | ||
3140 | n->type = EET_T_DOUBLE; | ||
3141 | sscanf(tok4, "%lf", | ||
3142 | &(n->data.value.d)); | ||
3143 | } | ||
3144 | else if (!strcmp(tok3, "uchar:")) | ||
3145 | { | ||
3146 | n->type = EET_T_UCHAR; | ||
3147 | sscanf(tok4, FMT_UCHAR, | ||
3148 | &(n->data.value.uc)); | ||
3149 | } | ||
3150 | else if (!strcmp(tok3, "ushort:")) | ||
3151 | { | ||
3152 | n->type = EET_T_USHORT; | ||
3153 | sscanf(tok4, "%hu", | ||
3154 | &(n->data.value.us)); | ||
3155 | } | ||
3156 | else if (!strcmp(tok3, "uint:")) | ||
3157 | { | ||
3158 | n->type = EET_T_UINT; | ||
3159 | sscanf(tok4, "%u", | ||
3160 | &(n->data.value.ui)); | ||
3161 | } | ||
3162 | else if (!strcmp(tok3, "ulong_long:")) | ||
3163 | { | ||
3164 | n->type = EET_T_ULONG_LONG; | ||
3165 | sscanf(tok4, FMT_ULONG_LONG, | ||
3166 | &(n->data.value.ul)); | ||
3167 | } | ||
3168 | else if (!strcmp(tok3, "string:")) | ||
3169 | { | ||
3170 | n->type = EET_T_STRING; | ||
3171 | n->data.value.str = | ||
3172 | eina_stringshare_add(tok4); | ||
3173 | } | ||
3174 | else if (!strcmp(tok3, "inlined:")) | ||
3175 | { | ||
3176 | n->type = EET_T_INLINED_STRING; | ||
3177 | n->data.value.str = | ||
3178 | eina_stringshare_add(tok4); | ||
3179 | } | ||
3180 | else if (!strcmp(tok3, "null")) | ||
3181 | { | ||
3182 | n->type = EET_T_NULL; | ||
3183 | n->data.value.str = NULL; | ||
3184 | } | ||
3185 | else | ||
3186 | ERR( | ||
3187 | "ERROR: value type '%s' invalid.", | ||
3188 | tok4); | ||
3189 | } | ||
3190 | } | ||
3191 | |||
3192 | free(tok4); | ||
3193 | } | ||
3194 | |||
3195 | free(tok3); | ||
3196 | } | ||
3197 | |||
3198 | free(tok2); | ||
3199 | } | ||
3200 | } | ||
3201 | else if (!strcmp(tok1, "key")) | ||
3202 | { | ||
3203 | TOK_GET(tok2); | ||
3204 | if (tok2) | ||
3205 | { | ||
3206 | /* we have 'key NAME' */ | ||
3207 | if (node) | ||
3208 | node->key = eina_stringshare_add(tok2); | ||
3209 | |||
3210 | free(tok2); | ||
3211 | } | ||
3212 | } | ||
3213 | else if (!strcmp(tok1, "count")) | ||
3214 | { | ||
3215 | TOK_GET(tok2); | ||
3216 | if (tok2) | ||
3217 | { | ||
3218 | /* we have a 'count COUNT' */ | ||
3219 | if (node) | ||
3220 | sscanf(tok2, "%i", &(node->count)); | ||
3221 | |||
3222 | free(tok2); | ||
3223 | } | ||
3224 | } | ||
3225 | else if (!strcmp(tok1, "}")) | ||
3226 | /* we have an end of the group */ | ||
3227 | if (node) | ||
3228 | node = node->parent; | ||
3229 | |||
3230 | free(tok1); | ||
3231 | } | ||
3232 | } | ||
3233 | |||
3234 | if (node_base) | ||
3235 | { | ||
3236 | cdata = _eet_data_dump_encode(EET_G_UNKNOWN, ed, node_base, size_ret); | ||
3237 | eet_node_del(node_base); | ||
3238 | } | ||
3239 | |||
3240 | return cdata; | ||
3241 | } /* _eet_data_dump_parse */ | ||
3242 | |||
3243 | #define NEXT_CHUNK(P, Size, Echnk, Ed) \ | ||
3244 | { \ | ||
3245 | int __tmp; \ | ||
3246 | __tmp = Ed ? (int)(sizeof(int) * 2) : Echnk.len + 4; \ | ||
3247 | P += (4 + Echnk.size + __tmp); \ | ||
3248 | Size -= (4 + Echnk.size + __tmp); \ | ||
3249 | } | ||
3250 | |||
3251 | static void * | ||
3252 | _eet_data_descriptor_decode(Eet_Free_Context *context, | ||
3253 | const Eet_Dictionary *ed, | ||
3254 | Eet_Data_Descriptor *edd, | ||
3255 | const void *data_in, | ||
3256 | int size_in, | ||
3257 | void *data_out, | ||
3258 | int size_out) | ||
3259 | { | ||
3260 | Eet_Node *result = NULL; | ||
3261 | void *data = NULL; | ||
3262 | char *p; | ||
3263 | int size, i; | ||
3264 | Eet_Data_Chunk chnk; | ||
3265 | |||
3266 | if (_eet_data_words_bigendian == -1) | ||
3267 | { | ||
3268 | unsigned long int v; | ||
3269 | |||
3270 | v = htonl(0x12345678); | ||
3271 | if (v == 0x12345678) | ||
3272 | _eet_data_words_bigendian = 1; | ||
3273 | else | ||
3274 | _eet_data_words_bigendian = 0; | ||
3275 | } | ||
3276 | |||
3277 | if (edd) | ||
3278 | { | ||
3279 | if (data_out) | ||
3280 | { | ||
3281 | if (size_out <= edd->size) | ||
3282 | data = data_out; | ||
3283 | } | ||
3284 | else | ||
3285 | { | ||
3286 | data = edd->func.mem_alloc(edd->size); | ||
3287 | } | ||
3288 | |||
3289 | if (!data) | ||
3290 | return NULL; | ||
3291 | |||
3292 | if (edd->ed != ed) | ||
3293 | { | ||
3294 | for (i = 0; i < edd->elements.num; i++) | ||
3295 | edd->elements.set[i].directory_name_ptr = NULL; | ||
3296 | edd->ed = ed; | ||
3297 | } | ||
3298 | } | ||
3299 | |||
3300 | _eet_freelist_all_ref(context); | ||
3301 | if (data && !data_out) | ||
3302 | _eet_freelist_add(context, data); | ||
3303 | |||
3304 | memset(&chnk, 0, sizeof(Eet_Data_Chunk)); | ||
3305 | eet_data_chunk_get(ed, &chnk, data_in, size_in); | ||
3306 | if (!chnk.name) | ||
3307 | goto error; | ||
3308 | |||
3309 | if (edd) | ||
3310 | if (strcmp(chnk.name, edd->name)) | ||
3311 | goto error; | ||
3312 | |||
3313 | p = chnk.data; | ||
3314 | if (ed) | ||
3315 | size = size_in - (4 + sizeof(int) * 2); | ||
3316 | else | ||
3317 | size = size_in - (4 + 4 + chnk.len); | ||
3318 | |||
3319 | if (edd) | ||
3320 | { | ||
3321 | if (!edd->elements.hash.buckets) | ||
3322 | _eet_descriptor_hash_new(edd); | ||
3323 | } | ||
3324 | else | ||
3325 | { | ||
3326 | switch (chnk.group_type) | ||
3327 | { | ||
3328 | case EET_G_UNKNOWN: | ||
3329 | switch (chnk.type) | ||
3330 | { | ||
3331 | case EET_T_STRING: | ||
3332 | return eet_node_string_new(chnk.name, chnk.data); | ||
3333 | |||
3334 | case EET_T_INLINED_STRING: | ||
3335 | return eet_node_inlined_string_new(chnk.name, chnk.data); | ||
3336 | |||
3337 | case EET_T_NULL: | ||
3338 | return eet_node_null_new(chnk.name); | ||
3339 | |||
3340 | default: | ||
3341 | result = eet_node_struct_new(chnk.name, NULL); | ||
3342 | } /* switch */ | ||
3343 | break; | ||
3344 | |||
3345 | case EET_G_VAR_ARRAY: | ||
3346 | return eet_node_var_array_new(chnk.name, NULL); | ||
3347 | |||
3348 | case EET_G_LIST: | ||
3349 | case EET_G_HASH: | ||
3350 | case EET_G_ARRAY: | ||
3351 | case EET_G_UNION: | ||
3352 | case EET_G_VARIANT: | ||
3353 | default: | ||
3354 | goto error; | ||
3355 | } /* switch */ | ||
3356 | } | ||
3357 | |||
3358 | while (size > 0) | ||
3359 | { | ||
3360 | Eet_Data_Chunk echnk; | ||
3361 | Eet_Data_Element *ede = NULL; | ||
3362 | Eet_Node *child = NULL; | ||
3363 | int group_type = EET_G_UNKNOWN, type = EET_T_UNKNOW; | ||
3364 | int ret = 0; | ||
3365 | |||
3366 | /* get next data chunk */ | ||
3367 | memset(&echnk, 0, sizeof(Eet_Data_Chunk)); | ||
3368 | eet_data_chunk_get(ed, &echnk, p, size); | ||
3369 | if (!echnk.name) | ||
3370 | goto error; /* FIXME: don't REPLY on edd - work without */ | ||
3371 | |||
3372 | if (edd) | ||
3373 | { | ||
3374 | ede = _eet_descriptor_hash_find(edd, echnk.name, echnk.hash); | ||
3375 | if (ede) | ||
3376 | { | ||
3377 | group_type = ede->group_type; | ||
3378 | type = ede->type; | ||
3379 | if ((echnk.type == 0) && (echnk.group_type == 0)) | ||
3380 | { | ||
3381 | type = ede->type; | ||
3382 | group_type = ede->group_type; | ||
3383 | } | ||
3384 | else | ||
3385 | { | ||
3386 | if (IS_SIMPLE_TYPE(echnk.type) && | ||
3387 | eet_data_type_match(echnk.type, ede->type)) | ||
3388 | /* Needed when converting on the fly from FP to Float */ | ||
3389 | type = ede->type; | ||
3390 | else if ((echnk.group_type > EET_G_UNKNOWN) && | ||
3391 | (echnk.group_type < EET_G_LAST) && | ||
3392 | (echnk.group_type == ede->group_type)) | ||
3393 | group_type = echnk.group_type; | ||
3394 | } | ||
3395 | } | ||
3396 | } | ||
3397 | /*...... dump to node */ | ||
3398 | else | ||
3399 | { | ||
3400 | type = echnk.type; | ||
3401 | group_type = echnk.group_type; | ||
3402 | } | ||
3403 | |||
3404 | if (!edd && group_type == EET_G_UNKNOWN && IS_SIMPLE_TYPE(type)) | ||
3405 | { | ||
3406 | unsigned char dd[128]; | ||
3407 | |||
3408 | ret = eet_data_get_type(ed, | ||
3409 | type, | ||
3410 | echnk.data, | ||
3411 | ((char *)echnk.data) + echnk.size, | ||
3412 | dd); | ||
3413 | if (ret <= 0) | ||
3414 | goto error; | ||
3415 | |||
3416 | child = eet_data_node_simple_type(type, echnk.name, dd); | ||
3417 | |||
3418 | eet_node_struct_append(result, echnk.name, child); | ||
3419 | } | ||
3420 | else | ||
3421 | { | ||
3422 | ret = eet_group_codec[group_type - 100].get( | ||
3423 | context, | ||
3424 | ed, | ||
3425 | edd, | ||
3426 | ede, | ||
3427 | &echnk, | ||
3428 | type, | ||
3429 | group_type, | ||
3430 | ede ? (void *)(((char *)data) + ede->offset) : (void **)&result, | ||
3431 | &p, | ||
3432 | &size); | ||
3433 | |||
3434 | if (ret <= 0) | ||
3435 | goto error; | ||
3436 | } | ||
3437 | |||
3438 | /* advance to next chunk */ | ||
3439 | NEXT_CHUNK(p, size, echnk, ed); | ||
3440 | } | ||
3441 | |||
3442 | _eet_freelist_all_unref(context); | ||
3443 | if (!edd) | ||
3444 | { | ||
3445 | _eet_freelist_str_free(context, edd); | ||
3446 | _eet_freelist_direct_str_free(context, edd); | ||
3447 | _eet_freelist_list_free(context, edd); | ||
3448 | _eet_freelist_hash_free(context, edd); | ||
3449 | _eet_freelist_array_free(context, edd); | ||
3450 | _eet_freelist_free(context, edd); | ||
3451 | } | ||
3452 | else | ||
3453 | { | ||
3454 | _eet_freelist_reset(context); | ||
3455 | _eet_freelist_str_reset(context); | ||
3456 | _eet_freelist_list_reset(context); | ||
3457 | _eet_freelist_hash_reset(context); | ||
3458 | _eet_freelist_direct_str_reset(context); | ||
3459 | _eet_freelist_array_reset(context); | ||
3460 | } | ||
3461 | |||
3462 | if (!edd) | ||
3463 | return result; | ||
3464 | |||
3465 | return data; | ||
3466 | |||
3467 | error: | ||
3468 | eet_node_del(result); | ||
3469 | |||
3470 | _eet_freelist_all_unref(context); | ||
3471 | _eet_freelist_str_free(context, edd); | ||
3472 | _eet_freelist_direct_str_free(context, edd); | ||
3473 | _eet_freelist_list_free(context, edd); | ||
3474 | _eet_freelist_hash_free(context, edd); | ||
3475 | _eet_freelist_array_free(context, edd); | ||
3476 | _eet_freelist_free(context, edd); | ||
3477 | |||
3478 | /* FIXME: Warn that something goes wrong here. */ | ||
3479 | return NULL; | ||
3480 | } /* _eet_data_descriptor_decode */ | ||
3481 | |||
3482 | static int | ||
3483 | eet_data_get_list(Eet_Free_Context *context, | ||
3484 | const Eet_Dictionary *ed, | ||
3485 | Eet_Data_Descriptor *edd, | ||
3486 | Eet_Data_Element *ede, | ||
3487 | Eet_Data_Chunk *echnk, | ||
3488 | int type, | ||
3489 | int group_type __UNUSED__, | ||
3490 | void *data, | ||
3491 | char **p, | ||
3492 | int *size) | ||
3493 | { | ||
3494 | Eet_Data_Descriptor *subtype = NULL; | ||
3495 | void *list = NULL; | ||
3496 | void **ptr; | ||
3497 | void *data_ret; | ||
3498 | |||
3499 | EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0); | ||
3500 | |||
3501 | if (ede) | ||
3502 | { | ||
3503 | subtype = ede->subtype; | ||
3504 | |||
3505 | if (type != ede->type) | ||
3506 | return 0; | ||
3507 | } | ||
3508 | |||
3509 | ptr = (void **)data; | ||
3510 | list = *ptr; | ||
3511 | data_ret = NULL; | ||
3512 | |||
3513 | if (IS_POINTER_TYPE(type)) | ||
3514 | POINTER_TYPE_DECODE(context, | ||
3515 | ed, | ||
3516 | edd, | ||
3517 | ede, | ||
3518 | echnk, | ||
3519 | type, | ||
3520 | &data_ret, | ||
3521 | p, | ||
3522 | size, | ||
3523 | on_error); | ||
3524 | else | ||
3525 | STRUCT_TYPE_DECODE(data_ret, | ||
3526 | context, | ||
3527 | ed, | ||
3528 | subtype, | ||
3529 | echnk->data, | ||
3530 | echnk->size, | ||
3531 | -1, | ||
3532 | on_error); | ||
3533 | |||
3534 | if (edd) | ||
3535 | { | ||
3536 | list = edd->func.list_append(list, data_ret); | ||
3537 | *ptr = list; | ||
3538 | _eet_freelist_list_add(context, ptr); | ||
3539 | } | ||
3540 | else | ||
3541 | eet_node_list_append(*((Eet_Node **)data), echnk->name, data_ret); | ||
3542 | |||
3543 | return 1; | ||
3544 | |||
3545 | on_error: | ||
3546 | return 0; | ||
3547 | } /* eet_data_get_list */ | ||
3548 | |||
3549 | static int | ||
3550 | eet_data_get_hash(Eet_Free_Context *context, | ||
3551 | const Eet_Dictionary *ed, | ||
3552 | Eet_Data_Descriptor *edd, | ||
3553 | Eet_Data_Element *ede, | ||
3554 | Eet_Data_Chunk *echnk, | ||
3555 | int type, | ||
3556 | int group_type __UNUSED__, | ||
3557 | void *data, | ||
3558 | char **p, | ||
3559 | int *size) | ||
3560 | { | ||
3561 | void **ptr; | ||
3562 | void *hash = NULL; | ||
3563 | char *key = NULL; | ||
3564 | void *data_ret = NULL; | ||
3565 | int ret = 0; | ||
3566 | |||
3567 | EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0); | ||
3568 | |||
3569 | ptr = (void **)data; | ||
3570 | hash = *ptr; | ||
3571 | |||
3572 | /* Read key */ | ||
3573 | ret = eet_data_get_type(ed, | ||
3574 | EET_T_STRING, | ||
3575 | echnk->data, | ||
3576 | ((char *)echnk->data) + echnk->size, | ||
3577 | &key); | ||
3578 | if (ret <= 0) | ||
3579 | goto on_error; | ||
3580 | |||
3581 | if (!key) | ||
3582 | goto on_error; | ||
3583 | |||
3584 | /* Advance to next chunk */ | ||
3585 | NEXT_CHUNK((*p), (*size), (*echnk), ed); | ||
3586 | memset(echnk, 0, sizeof(Eet_Data_Chunk)); | ||
3587 | |||
3588 | /* Read value */ | ||
3589 | eet_data_chunk_get(ed, echnk, *p, *size); | ||
3590 | if (!echnk->name) | ||
3591 | goto on_error; | ||
3592 | |||
3593 | if (ede) | ||
3594 | if ((ede->group_type != echnk->group_type) | ||
3595 | || (ede->type != echnk->type)) | ||
3596 | goto on_error; | ||
3597 | |||
3598 | if (IS_POINTER_TYPE(echnk->type)) | ||
3599 | POINTER_TYPE_DECODE(context, | ||
3600 | ed, | ||
3601 | edd, | ||
3602 | ede, | ||
3603 | echnk, | ||
3604 | echnk->type, | ||
3605 | &data_ret, | ||
3606 | p, | ||
3607 | size, | ||
3608 | on_error); | ||
3609 | else | ||
3610 | STRUCT_TYPE_DECODE(data_ret, | ||
3611 | context, | ||
3612 | ed, | ||
3613 | ede ? ede->subtype : NULL, | ||
3614 | echnk->data, | ||
3615 | echnk->size, | ||
3616 | -1, | ||
3617 | on_error); | ||
3618 | |||
3619 | if (edd) | ||
3620 | { | ||
3621 | hash = edd->func.hash_add(hash, key, data_ret); | ||
3622 | *ptr = hash; | ||
3623 | _eet_freelist_hash_add(context, hash); | ||
3624 | } | ||
3625 | else | ||
3626 | eet_node_hash_add(*((Eet_Node **)data), echnk->name, key, data_ret); | ||
3627 | |||
3628 | return 1; | ||
3629 | |||
3630 | on_error: | ||
3631 | return 0; | ||
3632 | } /* eet_data_get_hash */ | ||
3633 | |||
3634 | /* var arrays and fixed arrays have to | ||
3635 | * get all chunks at once. for fixed arrays | ||
3636 | * we can get each chunk and increment a | ||
3637 | * counter stored on the element itself but | ||
3638 | * it wont be thread safe. for var arrays | ||
3639 | * we still need a way to get the number of | ||
3640 | * elements from the data, so storing the | ||
3641 | * number of elements and the element data on | ||
3642 | * each chunk is pointless. | ||
3643 | */ | ||
3644 | static int | ||
3645 | eet_data_get_array(Eet_Free_Context *context, | ||
3646 | const Eet_Dictionary *ed, | ||
3647 | Eet_Data_Descriptor *edd, | ||
3648 | Eet_Data_Element *ede, | ||
3649 | Eet_Data_Chunk *echnk, | ||
3650 | int type, | ||
3651 | int group_type, | ||
3652 | void *data, | ||
3653 | char **p, | ||
3654 | int *size) | ||
3655 | { | ||
3656 | Eina_List *childs = NULL; | ||
3657 | const char *name; | ||
3658 | Eet_Node *tmp; | ||
3659 | void *ptr; | ||
3660 | int count; | ||
3661 | int ret; | ||
3662 | int subsize = 0; | ||
3663 | int i; | ||
3664 | |||
3665 | EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0); | ||
3666 | |||
3667 | ptr = data; | ||
3668 | /* read the number of elements */ | ||
3669 | ret = eet_data_get_type(ed, | ||
3670 | EET_T_INT, | ||
3671 | echnk->data, | ||
3672 | ((char *)echnk->data) + echnk->size, | ||
3673 | &count); | ||
3674 | if (ret <= 0) | ||
3675 | return ret; | ||
3676 | |||
3677 | name = echnk->name; | ||
3678 | |||
3679 | if (ede) | ||
3680 | { | ||
3681 | if (IS_POINTER_TYPE(type)) | ||
3682 | subsize = eet_basic_codec[ede->type].size; | ||
3683 | else | ||
3684 | subsize = ede->subtype->size; | ||
3685 | |||
3686 | if (group_type == EET_G_VAR_ARRAY) | ||
3687 | { | ||
3688 | /* store the number of elements | ||
3689 | * on the counter offset */ | ||
3690 | *(int *)(((char *)data) + ede->count - ede->offset) = count; | ||
3691 | /* allocate space for the array of elements */ | ||
3692 | if (edd->func.array_alloc) | ||
3693 | *(void **)ptr = edd->func.array_alloc(count * subsize); | ||
3694 | else | ||
3695 | *(void **)ptr = edd->func.mem_alloc(count * subsize); | ||
3696 | |||
3697 | if (!*(void **)ptr) | ||
3698 | return 0; | ||
3699 | |||
3700 | memset(*(void **)ptr, 0, count * subsize); | ||
3701 | |||
3702 | _eet_freelist_array_add(context, *(void **)ptr); | ||
3703 | } | ||
3704 | } | ||
3705 | |||
3706 | /* get all array elements */ | ||
3707 | for (i = 0; i < count; i++) | ||
3708 | { | ||
3709 | void *dst = NULL; | ||
3710 | |||
3711 | /* Advance to next chunk */ | ||
3712 | NEXT_CHUNK((*p), (*size), (*echnk), ed); | ||
3713 | memset(echnk, 0, sizeof(Eet_Data_Chunk)); | ||
3714 | |||
3715 | eet_data_chunk_get(ed, echnk, *p, *size); | ||
3716 | if (!echnk->name || strcmp(echnk->name, name) != 0) | ||
3717 | goto on_error; /* get the data */ | ||
3718 | |||
3719 | if ((echnk->group_type != group_type) | ||
3720 | || ((echnk->type != type) && (echnk->type != EET_T_NULL))) | ||
3721 | goto on_error; | ||
3722 | |||
3723 | if (ede) | ||
3724 | if ((ede->group_type != echnk->group_type) | ||
3725 | || ((echnk->type != ede->type) && (echnk->type != EET_T_NULL))) | ||
3726 | goto on_error; | ||
3727 | |||
3728 | /* get the destination pointer */ | ||
3729 | if (ede) | ||
3730 | { | ||
3731 | if (group_type == EET_G_ARRAY) | ||
3732 | dst = (char *)ptr + (subsize * i); | ||
3733 | else | ||
3734 | dst = *(char **)ptr + (subsize * i); | ||
3735 | } | ||
3736 | |||
3737 | if (IS_POINTER_TYPE(echnk->type)) | ||
3738 | { | ||
3739 | void *data_ret = NULL; | ||
3740 | |||
3741 | POINTER_TYPE_DECODE(context, | ||
3742 | ed, | ||
3743 | edd, | ||
3744 | ede, | ||
3745 | echnk, | ||
3746 | echnk->type, | ||
3747 | &data_ret, | ||
3748 | p, | ||
3749 | size, | ||
3750 | on_error); | ||
3751 | if (dst) | ||
3752 | memcpy(dst, &data_ret, subsize); | ||
3753 | |||
3754 | if (!edd) | ||
3755 | childs = eina_list_append(childs, data_ret); | ||
3756 | } | ||
3757 | else | ||
3758 | { | ||
3759 | STRUCT_TYPE_DECODE(dst, | ||
3760 | context, | ||
3761 | ed, | ||
3762 | ede ? ede->subtype : NULL, | ||
3763 | echnk->data, | ||
3764 | echnk->size, | ||
3765 | subsize, | ||
3766 | on_error); | ||
3767 | |||
3768 | if (!edd) | ||
3769 | childs = eina_list_append(childs, dst); | ||
3770 | } | ||
3771 | } | ||
3772 | |||
3773 | if (!edd) | ||
3774 | { | ||
3775 | Eet_Node *parent = *((Eet_Node **)data); | ||
3776 | Eet_Node *array; | ||
3777 | |||
3778 | if (group_type == EET_G_ARRAY) | ||
3779 | array = eet_node_array_new(name, count, childs); | ||
3780 | else | ||
3781 | array = eet_node_var_array_new(name, childs); | ||
3782 | |||
3783 | if (!array) | ||
3784 | goto on_error; | ||
3785 | |||
3786 | eet_node_struct_append(parent, name, array); | ||
3787 | } | ||
3788 | |||
3789 | return 1; | ||
3790 | |||
3791 | on_error: | ||
3792 | EINA_LIST_FREE(childs, tmp) | ||
3793 | eet_node_del(tmp); | ||
3794 | |||
3795 | return 0; | ||
3796 | } /* eet_data_get_array */ | ||
3797 | |||
3798 | static void | ||
3799 | eet_data_put_union(Eet_Dictionary *ed, | ||
3800 | Eet_Data_Descriptor *edd __UNUSED__, | ||
3801 | Eet_Data_Element *ede, | ||
3802 | Eet_Data_Stream *ds, | ||
3803 | void *data_in) | ||
3804 | { | ||
3805 | const char *union_type; | ||
3806 | int i; | ||
3807 | |||
3808 | EET_ASSERT(!((ede->type != EET_T_UNKNOW) || (!ede->subtype)), return ); | ||
3809 | |||
3810 | union_type = ede->subtype->func.type_get( | ||
3811 | ((char *)data_in) + ede->count - ede->offset, | ||
3812 | NULL); | ||
3813 | |||
3814 | if (!union_type) | ||
3815 | return; | ||
3816 | |||
3817 | /* Search the structure of the union to encode. */ | ||
3818 | for (i = 0; i < ede->subtype->elements.num; ++i) | ||
3819 | if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0) | ||
3820 | { | ||
3821 | Eet_Data_Element *sede; | ||
3822 | void *data; | ||
3823 | int size; | ||
3824 | |||
3825 | /* Yeah we found it ! */ | ||
3826 | data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size); | ||
3827 | if (data) | ||
3828 | eet_data_encode(ed, | ||
3829 | ds, | ||
3830 | data, | ||
3831 | ede->name, | ||
3832 | size, | ||
3833 | ede->type, | ||
3834 | ede->group_type); | ||
3835 | |||
3836 | sede = &(ede->subtype->elements.set[i]); | ||
3837 | data = _eet_data_descriptor_encode(ed, | ||
3838 | sede->subtype, | ||
3839 | data_in, | ||
3840 | &size); | ||
3841 | if (data) | ||
3842 | eet_data_encode(ed, | ||
3843 | ds, | ||
3844 | data, | ||
3845 | ede->name, | ||
3846 | size, | ||
3847 | ede->type, | ||
3848 | ede->group_type); | ||
3849 | |||
3850 | break; | ||
3851 | } | ||
3852 | } /* eet_data_put_union */ | ||
3853 | |||
3854 | static int | ||
3855 | eet_data_get_union(Eet_Free_Context *context, | ||
3856 | const Eet_Dictionary *ed, | ||
3857 | Eet_Data_Descriptor *edd __UNUSED__, | ||
3858 | Eet_Data_Element *ede, | ||
3859 | Eet_Data_Chunk *echnk, | ||
3860 | int type, | ||
3861 | int group_type, | ||
3862 | void *data, | ||
3863 | char **p, | ||
3864 | int *size) | ||
3865 | { | ||
3866 | const char *union_type; | ||
3867 | void *data_ret = NULL; | ||
3868 | int ret = 0; | ||
3869 | int i; | ||
3870 | |||
3871 | /* Read type */ | ||
3872 | ret = eet_data_get_type(ed, | ||
3873 | EET_T_STRING, | ||
3874 | echnk->data, | ||
3875 | ((char *)echnk->data) + echnk->size, | ||
3876 | &union_type); | ||
3877 | if (ret <= 0) | ||
3878 | goto on_error; | ||
3879 | |||
3880 | /* Advance to next chunk */ | ||
3881 | NEXT_CHUNK((*p), (*size), (*echnk), ed); | ||
3882 | memset(echnk, 0, sizeof(Eet_Data_Chunk)); | ||
3883 | |||
3884 | /* Read value */ | ||
3885 | eet_data_chunk_get(ed, echnk, *p, *size); | ||
3886 | if (!echnk->name) | ||
3887 | goto on_error; | ||
3888 | |||
3889 | if (ede) | ||
3890 | { | ||
3891 | EET_ASSERT(!(ede->group_type != group_type || ede->type != type), | ||
3892 | goto on_error); | ||
3893 | |||
3894 | /* Search the structure of the union to decode */ | ||
3895 | for (i = 0; i < ede->subtype->elements.num; ++i) | ||
3896 | if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0) | ||
3897 | { | ||
3898 | Eet_Data_Element *sede; | ||
3899 | char *ut; | ||
3900 | |||
3901 | /* Yeah we found it ! */ | ||
3902 | sede = &(ede->subtype->elements.set[i]); | ||
3903 | EET_ASSERT(sede->subtype, goto on_error); | ||
3904 | |||
3905 | data_ret = _eet_data_descriptor_decode(context, | ||
3906 | ed, | ||
3907 | sede->subtype, | ||
3908 | echnk->data, | ||
3909 | echnk->size, | ||
3910 | data, | ||
3911 | sede->subtype->size); | ||
3912 | if (!data_ret) | ||
3913 | goto on_error; | ||
3914 | |||
3915 | /* Set union type. */ | ||
3916 | if ((!ed) || (!ede->subtype->func.str_direct_alloc)) | ||
3917 | { | ||
3918 | ut = ede->subtype->func.str_alloc(union_type); | ||
3919 | _eet_freelist_str_add(context, ut); | ||
3920 | } | ||
3921 | else | ||
3922 | { | ||
3923 | ut = ede->subtype->func.str_direct_alloc(union_type); | ||
3924 | _eet_freelist_direct_str_add(context, ut); | ||
3925 | } | ||
3926 | |||
3927 | ede->subtype->func.type_set( | ||
3928 | ut, | ||
3929 | ((char *)data) + ede->count - | ||
3930 | ede->offset, | ||
3931 | EINA_FALSE); | ||
3932 | |||
3933 | break; | ||
3934 | } | ||
3935 | } | ||
3936 | else | ||
3937 | { | ||
3938 | /* FIXME: generate node structure. */ | ||
3939 | data_ret = _eet_data_descriptor_decode(context, | ||
3940 | ed, NULL, | ||
3941 | echnk->data, echnk->size, | ||
3942 | NULL, 0); | ||
3943 | goto on_error; | ||
3944 | } | ||
3945 | |||
3946 | return 1; | ||
3947 | |||
3948 | on_error: | ||
3949 | return 0; | ||
3950 | } /* eet_data_get_union */ | ||
3951 | |||
3952 | static void | ||
3953 | eet_data_put_variant(Eet_Dictionary *ed, | ||
3954 | Eet_Data_Descriptor *edd __UNUSED__, | ||
3955 | Eet_Data_Element *ede, | ||
3956 | Eet_Data_Stream *ds, | ||
3957 | void *data_in) | ||
3958 | { | ||
3959 | const char *union_type; | ||
3960 | void *data; | ||
3961 | Eina_Bool unknow = EINA_FALSE; | ||
3962 | int size; | ||
3963 | int i; | ||
3964 | |||
3965 | EET_ASSERT(!((ede->type != EET_T_UNKNOW) || (!ede->subtype)), return ); | ||
3966 | |||
3967 | union_type = ede->subtype->func.type_get( | ||
3968 | ((char *)data_in) + ede->count - ede->offset, | ||
3969 | &unknow); | ||
3970 | |||
3971 | if (!union_type && unknow == EINA_FALSE) | ||
3972 | return; | ||
3973 | |||
3974 | if (unknow) | ||
3975 | { | ||
3976 | /* Handle opaque internal representation */ | ||
3977 | Eet_Variant_Unknow *evu; | ||
3978 | |||
3979 | data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size); | ||
3980 | if (data) | ||
3981 | eet_data_encode(ed, | ||
3982 | ds, | ||
3983 | data, | ||
3984 | ede->name, | ||
3985 | size, | ||
3986 | ede->type, | ||
3987 | ede->group_type); | ||
3988 | |||
3989 | evu = (Eet_Variant_Unknow *)data_in; | ||
3990 | if (evu && EINA_MAGIC_CHECK(evu, EET_MAGIC_VARIANT)) | ||
3991 | eet_data_encode(ed, | ||
3992 | ds, | ||
3993 | evu->data, | ||
3994 | ede->name, | ||
3995 | evu->size, | ||
3996 | ede->type, | ||
3997 | ede->group_type); | ||
3998 | } | ||
3999 | else | ||
4000 | /* Search the structure of the union to encode. */ | ||
4001 | for (i = 0; i < ede->subtype->elements.num; ++i) | ||
4002 | if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0) | ||
4003 | { | ||
4004 | Eet_Data_Element *sede; | ||
4005 | |||
4006 | /* Yeah we found it ! */ | ||
4007 | data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size); | ||
4008 | if (data) | ||
4009 | eet_data_encode(ed, | ||
4010 | ds, | ||
4011 | data, | ||
4012 | ede->name, | ||
4013 | size, | ||
4014 | ede->type, | ||
4015 | ede->group_type); | ||
4016 | |||
4017 | sede = &(ede->subtype->elements.set[i]); | ||
4018 | |||
4019 | if (sede->group_type != EET_G_UNKNOWN) | ||
4020 | { | ||
4021 | Eet_Data_Stream *lds; | ||
4022 | |||
4023 | lds = eet_data_stream_new(); | ||
4024 | eet_group_codec[sede->group_type - 100].put(ed, | ||
4025 | sede->subtype, | ||
4026 | sede, | ||
4027 | lds, | ||
4028 | data_in); | ||
4029 | if (lds->size != 0) | ||
4030 | { | ||
4031 | eet_data_encode(ed, ds, lds->data, ede->name, lds->pos, | ||
4032 | ede->type, ede->group_type); | ||
4033 | |||
4034 | lds->data = NULL; | ||
4035 | lds->size = 0; | ||
4036 | } | ||
4037 | else | ||
4038 | eet_data_encode(ed, ds, NULL, ede->name, 0, | ||
4039 | EET_T_NULL, ede->group_type); | ||
4040 | |||
4041 | eet_data_stream_free(lds); | ||
4042 | } | ||
4043 | else | ||
4044 | { | ||
4045 | data = _eet_data_descriptor_encode(ed, | ||
4046 | sede->subtype, | ||
4047 | *(void **)data_in, | ||
4048 | &size); | ||
4049 | if (data) | ||
4050 | eet_data_encode(ed, | ||
4051 | ds, | ||
4052 | data, | ||
4053 | ede->name, | ||
4054 | size, | ||
4055 | ede->type, | ||
4056 | ede->group_type); | ||
4057 | } | ||
4058 | |||
4059 | break; | ||
4060 | } | ||
4061 | } /* eet_data_put_variant */ | ||
4062 | |||
4063 | static int | ||
4064 | eet_data_get_variant(Eet_Free_Context *context, | ||
4065 | const Eet_Dictionary *ed, | ||
4066 | Eet_Data_Descriptor *edd __UNUSED__, | ||
4067 | Eet_Data_Element *ede, | ||
4068 | Eet_Data_Chunk *echnk, | ||
4069 | int type __UNUSED__, | ||
4070 | int group_type __UNUSED__, | ||
4071 | void *data, | ||
4072 | char **p, | ||
4073 | int *size) | ||
4074 | { | ||
4075 | const char *union_type; | ||
4076 | void *data_ret = NULL; | ||
4077 | int ret = 0; | ||
4078 | int i; | ||
4079 | |||
4080 | /* Read type */ | ||
4081 | ret = eet_data_get_type(ed, | ||
4082 | EET_T_STRING, | ||
4083 | echnk->data, | ||
4084 | ((char *)echnk->data) + echnk->size, | ||
4085 | &union_type); | ||
4086 | if (ret <= 0) | ||
4087 | goto on_error; | ||
4088 | |||
4089 | /* Advance to next chunk */ | ||
4090 | NEXT_CHUNK((*p), (*size), (*echnk), ed); | ||
4091 | memset(echnk, 0, sizeof(Eet_Data_Chunk)); | ||
4092 | |||
4093 | /* Read value */ | ||
4094 | eet_data_chunk_get(ed, echnk, *p, *size); | ||
4095 | if (!echnk->name) | ||
4096 | goto on_error; | ||
4097 | |||
4098 | if (ede) | ||
4099 | { | ||
4100 | char *ut; | ||
4101 | |||
4102 | EET_ASSERT(ede->subtype, goto on_error); | ||
4103 | |||
4104 | if ((!ed) || (!ede->subtype->func.str_direct_alloc)) | ||
4105 | { | ||
4106 | ut = ede->subtype->func.str_alloc(union_type); | ||
4107 | _eet_freelist_str_add(context, ut); | ||
4108 | } | ||
4109 | else | ||
4110 | { | ||
4111 | ut = ede->subtype->func.str_direct_alloc(union_type); | ||
4112 | _eet_freelist_direct_str_add(context, ut); | ||
4113 | } | ||
4114 | |||
4115 | /* Search the structure of the union to decode */ | ||
4116 | for (i = 0; i < ede->subtype->elements.num; ++i) | ||
4117 | if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0) | ||
4118 | { | ||
4119 | Eet_Data_Element *sede; | ||
4120 | |||
4121 | /* Yeah we found it ! */ | ||
4122 | sede = &(ede->subtype->elements.set[i]); | ||
4123 | |||
4124 | if (sede->group_type != EET_G_UNKNOWN) | ||
4125 | { | ||
4126 | Eet_Data_Chunk chnk; | ||
4127 | char *p2; | ||
4128 | int size2; | ||
4129 | |||
4130 | p2 = echnk->data; | ||
4131 | size2 = echnk->size; | ||
4132 | |||
4133 | /* Didn't find a proper way to provide this | ||
4134 | without duplicating code */ | ||
4135 | while (size2 > 0) | ||
4136 | { | ||
4137 | memset(&chnk, 0, sizeof(Eet_Data_Chunk)); | ||
4138 | eet_data_chunk_get(ed, &chnk, p2, size2); | ||
4139 | |||
4140 | if (!chnk.name) | ||
4141 | goto on_error; | ||
4142 | |||
4143 | ret = eet_group_codec[sede->group_type - 100].get | ||
4144 | (context, ed, sede->subtype, sede, &chnk, sede->type, | ||
4145 | sede->group_type, data, &p2, &size2); | ||
4146 | |||
4147 | if (ret <= 0) | ||
4148 | goto on_error; | ||
4149 | |||
4150 | /* advance to next chunk */ | ||
4151 | NEXT_CHUNK(p2, size2, chnk, ed); | ||
4152 | } | ||
4153 | |||
4154 | /* Put garbage so that we will not put eet_variant_unknow in it */ | ||
4155 | data_ret = (void *)data; | ||
4156 | |||
4157 | /* Set variant type. */ | ||
4158 | ede->subtype->func.type_set | ||
4159 | (ut, ((char *)data) + ede->count - ede->offset, | ||
4160 | EINA_FALSE); | ||
4161 | break; | ||
4162 | } | ||
4163 | |||
4164 | data_ret = _eet_data_descriptor_decode(context, | ||
4165 | ed, | ||
4166 | sede->subtype, | ||
4167 | echnk->data, | ||
4168 | echnk->size, | ||
4169 | NULL, 0); | ||
4170 | if (!data_ret) | ||
4171 | break; | ||
4172 | |||
4173 | /* And point to the variant data. */ | ||
4174 | *(void **)data = data_ret; | ||
4175 | |||
4176 | /* Set variant type. */ | ||
4177 | ede->subtype->func.type_set | ||
4178 | (ut, ((char *)data) + ede->count - ede->offset, EINA_FALSE); | ||
4179 | break; | ||
4180 | } | ||
4181 | |||
4182 | if (!data_ret) | ||
4183 | { | ||
4184 | Eet_Variant_Unknow *evu; | ||
4185 | |||
4186 | evu = calloc(1, sizeof (Eet_Variant_Unknow) + echnk->size - 1); | ||
4187 | if (!evu) | ||
4188 | goto on_error; | ||
4189 | |||
4190 | evu->size = echnk->size; | ||
4191 | memcpy(evu->data, echnk->data, evu->size); | ||
4192 | EINA_MAGIC_SET(evu, EET_MAGIC_VARIANT); | ||
4193 | |||
4194 | /* And point to the opaque internal data scructure */ | ||
4195 | *(void **)data = evu; | ||
4196 | |||
4197 | /* Set variant type. */ | ||
4198 | ede->subtype->func.type_set | ||
4199 | (ut, ((char *)data) + ede->count - ede->offset, EINA_TRUE); | ||
4200 | } | ||
4201 | } | ||
4202 | else | ||
4203 | { | ||
4204 | /* FIXME: dump node structure. */ | ||
4205 | data_ret = _eet_data_descriptor_decode(context, | ||
4206 | ed, NULL, | ||
4207 | echnk->data, echnk->size, | ||
4208 | NULL, 0); | ||
4209 | goto on_error; | ||
4210 | } | ||
4211 | |||
4212 | return 1; | ||
4213 | |||
4214 | on_error: | ||
4215 | return 0; | ||
4216 | } /* eet_data_get_variant */ | ||
4217 | |||
4218 | static Eet_Node * | ||
4219 | eet_data_node_simple_type(int type, | ||
4220 | const char *name, | ||
4221 | void *dd) | ||
4222 | { | ||
4223 | #ifdef EET_T_TYPE | ||
4224 | # undef EET_T_TYPE | ||
4225 | #endif /* ifdef EET_T_TYPE */ | ||
4226 | |||
4227 | #define EET_T_TYPE(Eet_Type, Eet_Node_Type, Type) \ | ||
4228 | case Eet_Type: \ | ||
4229 | return eet_node_ ## Eet_Node_Type ## _new(name, *((Type *)dd)); \ | ||
4230 | |||
4231 | switch (type) | ||
4232 | { | ||
4233 | EET_T_TYPE(EET_T_CHAR, char, char); | ||
4234 | EET_T_TYPE(EET_T_SHORT, short, short); | ||
4235 | EET_T_TYPE(EET_T_INT, int, int); | ||
4236 | EET_T_TYPE(EET_T_LONG_LONG, long_long, long long); | ||
4237 | EET_T_TYPE(EET_T_FLOAT, float, float); | ||
4238 | EET_T_TYPE(EET_T_DOUBLE, double, double); | ||
4239 | EET_T_TYPE(EET_T_UCHAR, unsigned_char, unsigned char); | ||
4240 | EET_T_TYPE(EET_T_USHORT, unsigned_short, unsigned short); | ||
4241 | EET_T_TYPE(EET_T_UINT, unsigned_int, unsigned int); | ||
4242 | EET_T_TYPE(EET_T_ULONG_LONG, unsigned_long_long, unsigned long long); | ||
4243 | EET_T_TYPE(EET_T_STRING, string, char *); | ||
4244 | EET_T_TYPE(EET_T_INLINED_STRING, inlined_string, char *); | ||
4245 | |||
4246 | case EET_T_NULL: | ||
4247 | return eet_node_null_new(name); | ||
4248 | |||
4249 | default: | ||
4250 | ERR("Unknow type passed to eet_data_node_simple_type"); | ||
4251 | return NULL; | ||
4252 | } /* switch */ | ||
4253 | } /* eet_data_node_simple_type */ | ||
4254 | |||
4255 | static int | ||
4256 | eet_data_get_unknown(Eet_Free_Context *context, | ||
4257 | const Eet_Dictionary *ed, | ||
4258 | Eet_Data_Descriptor *edd, | ||
4259 | Eet_Data_Element *ede, | ||
4260 | Eet_Data_Chunk *echnk, | ||
4261 | int type, | ||
4262 | int group_type __UNUSED__, | ||
4263 | void *data, | ||
4264 | char **p __UNUSED__, | ||
4265 | int *size __UNUSED__) | ||
4266 | { | ||
4267 | int ret; | ||
4268 | void *data_ret; | ||
4269 | |||
4270 | if (IS_SIMPLE_TYPE(type)) | ||
4271 | { | ||
4272 | unsigned char dd[128]; | ||
4273 | |||
4274 | ret = eet_data_get_type(ed, | ||
4275 | type, | ||
4276 | echnk->data, | ||
4277 | ((char *)echnk->data) + echnk->size, | ||
4278 | edd ? (char *)data : (char *)dd); | ||
4279 | if (ret <= 0) | ||
4280 | return ret; | ||
4281 | |||
4282 | if (!edd) | ||
4283 | { | ||
4284 | Eet_Node **parent = data; | ||
4285 | Eet_Node *node; | ||
4286 | |||
4287 | node = eet_data_node_simple_type(type, echnk->name, dd); | ||
4288 | |||
4289 | if (*parent) | ||
4290 | eet_node_struct_append(*parent, echnk->name, node); | ||
4291 | else | ||
4292 | *parent = node; | ||
4293 | } | ||
4294 | else | ||
4295 | { | ||
4296 | if (type == EET_T_STRING) | ||
4297 | { | ||
4298 | char **str; | ||
4299 | |||
4300 | str = (char **)(((char *)data)); | ||
4301 | if (*str) | ||
4302 | { | ||
4303 | if ((!ed) || (!edd->func.str_direct_alloc)) | ||
4304 | { | ||
4305 | *str = edd->func.str_alloc(*str); | ||
4306 | _eet_freelist_str_add(context, *str); | ||
4307 | } | ||
4308 | else | ||
4309 | { | ||
4310 | *str = edd->func.str_direct_alloc(*str); | ||
4311 | _eet_freelist_direct_str_add(context, *str); | ||
4312 | } | ||
4313 | } | ||
4314 | } | ||
4315 | else if (edd && type == EET_T_INLINED_STRING) | ||
4316 | { | ||
4317 | char **str; | ||
4318 | |||
4319 | str = (char **)(((char *)data)); | ||
4320 | if (*str) | ||
4321 | { | ||
4322 | *str = edd->func.str_alloc(*str); | ||
4323 | _eet_freelist_str_add(context, *str); | ||
4324 | } | ||
4325 | } | ||
4326 | } | ||
4327 | } | ||
4328 | else | ||
4329 | { | ||
4330 | Eet_Data_Descriptor *subtype; | ||
4331 | |||
4332 | subtype = ede ? ede->subtype : NULL; | ||
4333 | |||
4334 | if (subtype || !edd) | ||
4335 | { | ||
4336 | Eet_Node **parent = data; | ||
4337 | void **ptr; | ||
4338 | |||
4339 | data_ret = _eet_data_descriptor_decode(context, | ||
4340 | ed, | ||
4341 | subtype, | ||
4342 | echnk->data, | ||
4343 | echnk->size, | ||
4344 | NULL, 0); | ||
4345 | if (!data_ret) | ||
4346 | return 0; | ||
4347 | |||
4348 | if (edd) | ||
4349 | { | ||
4350 | ptr = (void **)(((char *)data)); | ||
4351 | *ptr = (void *)data_ret; | ||
4352 | } | ||
4353 | else | ||
4354 | { | ||
4355 | Eet_Node *node = data_ret; | ||
4356 | |||
4357 | if (*parent) | ||
4358 | { | ||
4359 | node = eet_node_struct_child_new(echnk->name, node); | ||
4360 | eet_node_struct_append(*parent, echnk->name, node); | ||
4361 | } | ||
4362 | else | ||
4363 | *parent = node; | ||
4364 | } | ||
4365 | } | ||
4366 | } | ||
4367 | |||
4368 | return 1; | ||
4369 | } /* eet_data_get_unknown */ | ||
4370 | |||
4371 | static void | ||
4372 | eet_data_put_array(Eet_Dictionary *ed, | ||
4373 | Eet_Data_Descriptor *edd __UNUSED__, | ||
4374 | Eet_Data_Element *ede, | ||
4375 | Eet_Data_Stream *ds, | ||
4376 | void *data_in) | ||
4377 | { | ||
4378 | void *data; | ||
4379 | int offset = 0; | ||
4380 | int subsize; | ||
4381 | int count; | ||
4382 | int size; | ||
4383 | int j; | ||
4384 | |||
4385 | EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)), | ||
4386 | return ); | ||
4387 | |||
4388 | if (ede->group_type == EET_G_ARRAY) | ||
4389 | count = ede->counter_offset; | ||
4390 | else | ||
4391 | count = *(int *)(((char *)data_in) + ede->count - ede->offset); | ||
4392 | |||
4393 | if (count <= 0) | ||
4394 | return; /* Store number of elements */ | ||
4395 | |||
4396 | data = eet_data_put_type(ed, EET_T_INT, &count, &size); | ||
4397 | if (data) | ||
4398 | eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type); | ||
4399 | |||
4400 | if (IS_POINTER_TYPE(ede->type)) | ||
4401 | subsize = eet_basic_codec[ede->type].size; | ||
4402 | else | ||
4403 | subsize = ede->subtype->size; | ||
4404 | |||
4405 | for (j = 0; j < count; j++) | ||
4406 | { | ||
4407 | void *d; | ||
4408 | int pos = ds->pos; | ||
4409 | |||
4410 | if (ede->group_type == EET_G_ARRAY) | ||
4411 | d = (void *)(((char *)data_in) + offset); | ||
4412 | else | ||
4413 | d = *(((char **)data_in)) + offset; | ||
4414 | |||
4415 | if (IS_POINTER_TYPE(ede->type)) | ||
4416 | { | ||
4417 | if (*(char **)d) | ||
4418 | eet_data_put_unknown(ed, NULL, ede, ds, d); | ||
4419 | } | ||
4420 | else | ||
4421 | { | ||
4422 | data = _eet_data_descriptor_encode(ed, ede->subtype, d, &size); | ||
4423 | if (data) | ||
4424 | eet_data_encode(ed, | ||
4425 | ds, | ||
4426 | data, | ||
4427 | ede->name, | ||
4428 | size, | ||
4429 | ede->type, | ||
4430 | ede->group_type); | ||
4431 | } | ||
4432 | |||
4433 | if (pos == ds->pos) | ||
4434 | /* Add a NULL element just to have the correct array layout. */ | ||
4435 | eet_data_encode(ed, | ||
4436 | ds, | ||
4437 | NULL, | ||
4438 | ede->name, | ||
4439 | 0, | ||
4440 | EET_T_NULL, | ||
4441 | ede->group_type); | ||
4442 | |||
4443 | offset += subsize; | ||
4444 | } | ||
4445 | } /* eet_data_put_array */ | ||
4446 | |||
4447 | static void | ||
4448 | eet_data_put_unknown(Eet_Dictionary *ed, | ||
4449 | Eet_Data_Descriptor *edd __UNUSED__, | ||
4450 | Eet_Data_Element *ede, | ||
4451 | Eet_Data_Stream *ds, | ||
4452 | void *data_in) | ||
4453 | { | ||
4454 | void *data = NULL; | ||
4455 | int size; | ||
4456 | |||
4457 | if (IS_SIMPLE_TYPE(ede->type)) | ||
4458 | data = eet_data_put_type(ed, ede->type, data_in, &size); | ||
4459 | else if (ede->subtype) | ||
4460 | if (*((char **)data_in)) | ||
4461 | data = _eet_data_descriptor_encode(ed, | ||
4462 | ede->subtype, | ||
4463 | *((char **)((char *)(data_in))), | ||
4464 | &size); | ||
4465 | |||
4466 | if (data) | ||
4467 | eet_data_encode(ed, | ||
4468 | ds, | ||
4469 | data, | ||
4470 | ede->name, | ||
4471 | size, | ||
4472 | ede->type, | ||
4473 | ede->group_type); | ||
4474 | } /* eet_data_put_unknown */ | ||
4475 | |||
4476 | static void | ||
4477 | eet_data_put_list(Eet_Dictionary *ed, | ||
4478 | Eet_Data_Descriptor *edd, | ||
4479 | Eet_Data_Element *ede, | ||
4480 | Eet_Data_Stream *ds, | ||
4481 | void *data_in) | ||
4482 | { | ||
4483 | void *data; | ||
4484 | void *l; | ||
4485 | int size; | ||
4486 | |||
4487 | EET_ASSERT(!(((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)) | ||
4488 | || ((ede->type > EET_T_NULL) && (ede->type < EET_T_LAST))), | ||
4489 | return ); | ||
4490 | |||
4491 | l = *((void **)(((char *)data_in))); | ||
4492 | for (; l; l = edd->func.list_next(l)) | ||
4493 | { | ||
4494 | if (IS_POINTER_TYPE(ede->type)) | ||
4495 | { | ||
4496 | const void *str = edd->func.list_data(l); | ||
4497 | eet_data_put_unknown(ed, NULL, ede, ds, &str); | ||
4498 | } | ||
4499 | else | ||
4500 | { | ||
4501 | data = _eet_data_descriptor_encode(ed, | ||
4502 | ede->subtype, | ||
4503 | edd->func.list_data(l), | ||
4504 | &size); | ||
4505 | if (data) | ||
4506 | eet_data_encode(ed, | ||
4507 | ds, | ||
4508 | data, | ||
4509 | ede->name, | ||
4510 | size, | ||
4511 | ede->type, | ||
4512 | ede->group_type); | ||
4513 | } | ||
4514 | } | ||
4515 | } /* eet_data_put_list */ | ||
4516 | |||
4517 | static void | ||
4518 | eet_data_put_hash(Eet_Dictionary *ed, | ||
4519 | Eet_Data_Descriptor *edd, | ||
4520 | Eet_Data_Element *ede, | ||
4521 | Eet_Data_Stream *ds, | ||
4522 | void *data_in) | ||
4523 | { | ||
4524 | Eet_Data_Encode_Hash_Info fdata; | ||
4525 | void *l; | ||
4526 | |||
4527 | l = *((void **)(((char *)data_in))); | ||
4528 | fdata.ds = ds; | ||
4529 | fdata.ede = ede; | ||
4530 | fdata.ed = ed; | ||
4531 | edd->func.hash_foreach(l, eet_data_descriptor_encode_hash_cb, &fdata); | ||
4532 | } /* eet_data_put_hash */ | ||
4533 | |||
4534 | EAPI int | ||
4535 | eet_data_dump_cipher(Eet_File *ef, | ||
4536 | const char *name, | ||
4537 | const char *cipher_key, | ||
4538 | Eet_Dump_Callback dumpfunc, | ||
4539 | void *dumpdata) | ||
4540 | { | ||
4541 | const Eet_Dictionary *ed = NULL; | ||
4542 | const void *data = NULL; | ||
4543 | Eet_Node *result; | ||
4544 | Eet_Free_Context context; | ||
4545 | int required_free = 0; | ||
4546 | int size; | ||
4547 | |||
4548 | ed = eet_dictionary_get(ef); | ||
4549 | |||
4550 | if (!cipher_key) | ||
4551 | data = eet_read_direct(ef, name, &size); | ||
4552 | |||
4553 | if (!data) | ||
4554 | { | ||
4555 | required_free = 1; | ||
4556 | data = eet_read_cipher(ef, name, &size, cipher_key); | ||
4557 | if (!data) | ||
4558 | return 0; | ||
4559 | } | ||
4560 | |||
4561 | eet_free_context_init(&context); | ||
4562 | result = _eet_data_descriptor_decode(&context, ed, NULL, data, size, NULL, 0); | ||
4563 | eet_free_context_shutdown(&context); | ||
4564 | |||
4565 | eet_node_dump(result, 0, dumpfunc, dumpdata); | ||
4566 | |||
4567 | eet_node_del(result); | ||
4568 | |||
4569 | if (required_free) | ||
4570 | free((void *)data); | ||
4571 | |||
4572 | return result ? 1 : 0; | ||
4573 | } /* eet_data_dump_cipher */ | ||
4574 | |||
4575 | EAPI int | ||
4576 | eet_data_dump(Eet_File *ef, | ||
4577 | const char *name, | ||
4578 | Eet_Dump_Callback dumpfunc, | ||
4579 | void *dumpdata) | ||
4580 | { | ||
4581 | return eet_data_dump_cipher(ef, name, NULL, dumpfunc, dumpdata); | ||
4582 | } /* eet_data_dump */ | ||
4583 | |||
4584 | EAPI int | ||
4585 | eet_data_text_dump_cipher(const void *data_in, | ||
4586 | const char *cipher_key, | ||
4587 | int size_in, | ||
4588 | Eet_Dump_Callback dumpfunc, | ||
4589 | void *dumpdata) | ||
4590 | { | ||
4591 | void *ret = NULL; | ||
4592 | Eet_Node *result; | ||
4593 | Eet_Free_Context context; | ||
4594 | unsigned int ret_len = 0; | ||
4595 | |||
4596 | if (!data_in) | ||
4597 | return 0; | ||
4598 | |||
4599 | if (cipher_key) | ||
4600 | { | ||
4601 | if (eet_decipher(data_in, size_in, cipher_key, | ||
4602 | strlen(cipher_key), &ret, &ret_len)) | ||
4603 | { | ||
4604 | if (ret) | ||
4605 | free(ret); | ||
4606 | |||
4607 | return 0; | ||
4608 | } | ||
4609 | } | ||
4610 | else | ||
4611 | { | ||
4612 | ret = (void *)data_in; | ||
4613 | ret_len = size_in; | ||
4614 | } | ||
4615 | |||
4616 | eet_free_context_init(&context); | ||
4617 | result = _eet_data_descriptor_decode(&context, NULL, NULL, ret, ret_len, NULL, 0); | ||
4618 | eet_free_context_shutdown(&context); | ||
4619 | |||
4620 | eet_node_dump(result, 0, dumpfunc, dumpdata); | ||
4621 | |||
4622 | eet_node_del(result); | ||
4623 | if (cipher_key) | ||
4624 | free(ret); | ||
4625 | |||
4626 | return result ? 1 : 0; | ||
4627 | } /* eet_data_text_dump_cipher */ | ||
4628 | |||
4629 | EAPI int | ||
4630 | eet_data_text_dump(const void *data_in, | ||
4631 | int size_in, | ||
4632 | Eet_Dump_Callback dumpfunc, | ||
4633 | void *dumpdata) | ||
4634 | { | ||
4635 | return eet_data_text_dump_cipher(data_in, NULL, size_in, dumpfunc, dumpdata); | ||
4636 | } /* eet_data_text_dump */ | ||
4637 | |||
4638 | EAPI void * | ||
4639 | eet_data_text_undump_cipher(const char *text, | ||
4640 | const char *cipher_key, | ||
4641 | int textlen, | ||
4642 | int *size_ret) | ||
4643 | { | ||
4644 | void *ret = NULL; | ||
4645 | |||
4646 | ret = _eet_data_dump_parse(NULL, size_ret, text, textlen); | ||
4647 | if (ret && cipher_key) | ||
4648 | { | ||
4649 | void *ciphered = NULL; | ||
4650 | unsigned int ciphered_len; | ||
4651 | |||
4652 | if (eet_cipher(ret, *size_ret, cipher_key, | ||
4653 | strlen(cipher_key), &ciphered, &ciphered_len)) | ||
4654 | { | ||
4655 | if (ciphered) | ||
4656 | free(ciphered); | ||
4657 | |||
4658 | size_ret = 0; | ||
4659 | free(ret); | ||
4660 | return NULL; | ||
4661 | } | ||
4662 | |||
4663 | free(ret); | ||
4664 | *size_ret = ciphered_len; | ||
4665 | ret = ciphered; | ||
4666 | } | ||
4667 | |||
4668 | return ret; | ||
4669 | } /* eet_data_text_undump_cipher */ | ||
4670 | |||
4671 | EAPI void * | ||
4672 | eet_data_text_undump(const char *text, | ||
4673 | int textlen, | ||
4674 | int *size_ret) | ||
4675 | { | ||
4676 | return eet_data_text_undump_cipher(text, NULL, textlen, size_ret); | ||
4677 | } /* eet_data_text_undump */ | ||
4678 | |||
4679 | EAPI int | ||
4680 | eet_data_undump_cipher(Eet_File *ef, | ||
4681 | const char *name, | ||
4682 | const char *cipher_key, | ||
4683 | const char *text, | ||
4684 | int textlen, | ||
4685 | int compress) | ||
4686 | { | ||
4687 | Eet_Dictionary *ed; | ||
4688 | void *data_enc; | ||
4689 | int size; | ||
4690 | int val; | ||
4691 | |||
4692 | ed = eet_dictionary_get(ef); | ||
4693 | |||
4694 | data_enc = _eet_data_dump_parse(ed, &size, text, textlen); | ||
4695 | if (!data_enc) | ||
4696 | return 0; | ||
4697 | |||
4698 | val = eet_write_cipher(ef, name, data_enc, size, compress, cipher_key); | ||
4699 | free(data_enc); | ||
4700 | return val; | ||
4701 | } /* eet_data_undump_cipher */ | ||
4702 | |||
4703 | EAPI int | ||
4704 | eet_data_undump(Eet_File *ef, | ||
4705 | const char *name, | ||
4706 | const char *text, | ||
4707 | int textlen, | ||
4708 | int compress) | ||
4709 | { | ||
4710 | return eet_data_undump_cipher(ef, name, NULL, text, textlen, compress); | ||
4711 | } /* eet_data_undump */ | ||
4712 | |||
4713 | EAPI void * | ||
4714 | eet_data_descriptor_decode_cipher(Eet_Data_Descriptor *edd, | ||
4715 | const void *data_in, | ||
4716 | const char *cipher_key, | ||
4717 | int size_in) | ||
4718 | { | ||
4719 | void *deciphered = (void *)data_in; | ||
4720 | void *ret; | ||
4721 | Eet_Free_Context context; | ||
4722 | unsigned int deciphered_len = size_in; | ||
4723 | |||
4724 | if (cipher_key && data_in) | ||
4725 | if (eet_decipher(data_in, size_in, cipher_key, | ||
4726 | strlen(cipher_key), &deciphered, &deciphered_len)) | ||
4727 | { | ||
4728 | if (deciphered) | ||
4729 | free(deciphered); | ||
4730 | |||
4731 | return NULL; | ||
4732 | } | ||
4733 | |||
4734 | eet_free_context_init(&context); | ||
4735 | ret = _eet_data_descriptor_decode(&context, | ||
4736 | NULL, | ||
4737 | edd, | ||
4738 | deciphered, | ||
4739 | deciphered_len, | ||
4740 | NULL, 0); | ||
4741 | eet_free_context_shutdown(&context); | ||
4742 | |||
4743 | if (data_in != deciphered) | ||
4744 | free(deciphered); | ||
4745 | |||
4746 | return ret; | ||
4747 | } /* eet_data_descriptor_decode_cipher */ | ||
4748 | |||
4749 | EAPI void * | ||
4750 | eet_data_descriptor_decode(Eet_Data_Descriptor *edd, | ||
4751 | const void *data_in, | ||
4752 | int size_in) | ||
4753 | { | ||
4754 | return eet_data_descriptor_decode_cipher(edd, data_in, NULL, size_in); | ||
4755 | } /* eet_data_descriptor_decode */ | ||
4756 | |||
4757 | EAPI Eet_Node * | ||
4758 | eet_data_node_decode_cipher(const void *data_in, | ||
4759 | const char *cipher_key, | ||
4760 | int size_in) | ||
4761 | { | ||
4762 | void *deciphered = (void *)data_in; | ||
4763 | Eet_Node *ret; | ||
4764 | Eet_Free_Context context; | ||
4765 | unsigned int deciphered_len = size_in; | ||
4766 | |||
4767 | if (cipher_key && data_in) | ||
4768 | if (eet_decipher(data_in, size_in, cipher_key, | ||
4769 | strlen(cipher_key), &deciphered, &deciphered_len)) | ||
4770 | { | ||
4771 | if (deciphered) | ||
4772 | free(deciphered); | ||
4773 | |||
4774 | return NULL; | ||
4775 | } | ||
4776 | |||
4777 | eet_free_context_init(&context); | ||
4778 | ret = _eet_data_descriptor_decode(&context, | ||
4779 | NULL, | ||
4780 | NULL, | ||
4781 | deciphered, | ||
4782 | deciphered_len, | ||
4783 | NULL, 0); | ||
4784 | eet_free_context_shutdown(&context); | ||
4785 | |||
4786 | if (data_in != deciphered) | ||
4787 | free(deciphered); | ||
4788 | |||
4789 | return ret; | ||
4790 | } /* eet_data_node_decode_cipher */ | ||
4791 | |||
4792 | static void * | ||
4793 | _eet_data_descriptor_encode(Eet_Dictionary *ed, | ||
4794 | Eet_Data_Descriptor *edd, | ||
4795 | const void *data_in, | ||
4796 | int *size_ret) | ||
4797 | { | ||
4798 | Eet_Data_Stream *ds; | ||
4799 | Eet_Data_Chunk *chnk; | ||
4800 | void *cdata; | ||
4801 | int csize; | ||
4802 | int i; | ||
4803 | |||
4804 | if (_eet_data_words_bigendian == -1) | ||
4805 | { | ||
4806 | unsigned long int v; | ||
4807 | |||
4808 | v = htonl(0x12345678); | ||
4809 | if (v == 0x12345678) | ||
4810 | _eet_data_words_bigendian = 1; | ||
4811 | else | ||
4812 | _eet_data_words_bigendian = 0; | ||
4813 | } | ||
4814 | |||
4815 | ds = eet_data_stream_new(); | ||
4816 | for (i = 0; i < edd->elements.num; i++) | ||
4817 | { | ||
4818 | Eet_Data_Element *ede; | ||
4819 | |||
4820 | ede = &(edd->elements.set[i]); | ||
4821 | eet_group_codec[ede->group_type - 100].put( | ||
4822 | ed, | ||
4823 | edd, | ||
4824 | ede, | ||
4825 | ds, | ||
4826 | ((char *)data_in) + | ||
4827 | ede->offset); | ||
4828 | } | ||
4829 | chnk = eet_data_chunk_new(ds->data, | ||
4830 | ds->pos, | ||
4831 | edd->name, | ||
4832 | EET_T_UNKNOW, | ||
4833 | EET_G_UNKNOWN); | ||
4834 | ds->data = NULL; | ||
4835 | ds->size = 0; | ||
4836 | eet_data_stream_free(ds); | ||
4837 | |||
4838 | ds = eet_data_stream_new(); | ||
4839 | eet_data_chunk_put(ed, chnk, ds); | ||
4840 | cdata = ds->data; | ||
4841 | csize = ds->pos; | ||
4842 | |||
4843 | ds->data = NULL; | ||
4844 | ds->size = 0; | ||
4845 | eet_data_stream_free(ds); | ||
4846 | *size_ret = csize; | ||
4847 | |||
4848 | free(chnk->data); | ||
4849 | eet_data_chunk_free(chnk); | ||
4850 | |||
4851 | return cdata; | ||
4852 | } /* _eet_data_descriptor_encode */ | ||
4853 | |||
4854 | EAPI int | ||
4855 | eet_data_node_write_cipher(Eet_File *ef, | ||
4856 | const char *name, | ||
4857 | const char *cipher_key, | ||
4858 | Eet_Node *node, | ||
4859 | int compress) | ||
4860 | { | ||
4861 | Eet_Dictionary *ed; | ||
4862 | void *data_enc; | ||
4863 | int size; | ||
4864 | int val; | ||
4865 | |||
4866 | ed = eet_dictionary_get(ef); | ||
4867 | |||
4868 | data_enc = _eet_data_dump_encode(EET_G_UNKNOWN, ed, node, &size); | ||
4869 | if (!data_enc) | ||
4870 | return 0; | ||
4871 | |||
4872 | val = eet_write_cipher(ef, name, data_enc, size, compress, cipher_key); | ||
4873 | free(data_enc); | ||
4874 | return val; | ||
4875 | } /* eet_data_node_write_cipher */ | ||
4876 | |||
4877 | EAPI void * | ||
4878 | eet_data_node_encode_cipher(Eet_Node *node, | ||
4879 | const char *cipher_key, | ||
4880 | int *size_ret) | ||
4881 | { | ||
4882 | void *ret = NULL; | ||
4883 | void *ciphered = NULL; | ||
4884 | unsigned int ciphered_len = 0; | ||
4885 | int size; | ||
4886 | |||
4887 | ret = _eet_data_dump_encode(EET_G_UNKNOWN, NULL, node, &size); | ||
4888 | if (cipher_key && ret) | ||
4889 | { | ||
4890 | if (eet_cipher(ret, size, cipher_key, | ||
4891 | strlen(cipher_key), &ciphered, &ciphered_len)) | ||
4892 | { | ||
4893 | if (ciphered) | ||
4894 | free(ciphered); | ||
4895 | |||
4896 | if (size_ret) | ||
4897 | *size_ret = 0; | ||
4898 | |||
4899 | free(ret); | ||
4900 | return NULL; | ||
4901 | } | ||
4902 | |||
4903 | free(ret); | ||
4904 | size = (int)ciphered_len; | ||
4905 | ret = ciphered; | ||
4906 | } | ||
4907 | |||
4908 | if (size_ret) | ||
4909 | *size_ret = size; | ||
4910 | |||
4911 | return ret; | ||
4912 | } /* eet_data_node_encode_cipher */ | ||
4913 | |||
4914 | EAPI void * | ||
4915 | eet_data_descriptor_encode_cipher(Eet_Data_Descriptor *edd, | ||
4916 | const void *data_in, | ||
4917 | const char *cipher_key, | ||
4918 | int *size_ret) | ||
4919 | { | ||
4920 | void *ret = NULL; | ||
4921 | void *ciphered = NULL; | ||
4922 | unsigned int ciphered_len = 0; | ||
4923 | int size; | ||
4924 | |||
4925 | ret = _eet_data_descriptor_encode(NULL, edd, data_in, &size); | ||
4926 | if (cipher_key && ret) | ||
4927 | { | ||
4928 | if (eet_cipher(ret, size, cipher_key, | ||
4929 | strlen(cipher_key), &ciphered, &ciphered_len)) | ||
4930 | { | ||
4931 | if (ciphered) | ||
4932 | free(ciphered); | ||
4933 | |||
4934 | if (size_ret) | ||
4935 | *size_ret = 0; | ||
4936 | |||
4937 | free(ret); | ||
4938 | return NULL; | ||
4939 | } | ||
4940 | |||
4941 | free(ret); | ||
4942 | size = ciphered_len; | ||
4943 | ret = ciphered; | ||
4944 | } | ||
4945 | |||
4946 | if (size_ret) | ||
4947 | *size_ret = size; | ||
4948 | |||
4949 | return ret; | ||
4950 | } /* eet_data_descriptor_encode_cipher */ | ||
4951 | |||
4952 | EAPI void * | ||
4953 | eet_data_descriptor_encode(Eet_Data_Descriptor *edd, | ||
4954 | const void *data_in, | ||
4955 | int *size_ret) | ||
4956 | { | ||
4957 | return eet_data_descriptor_encode_cipher(edd, data_in, NULL, size_ret); | ||
4958 | } /* eet_data_descriptor_encode */ | ||
4959 | |||
4960 | EAPI void * | ||
4961 | eet_data_xattr_cipher_get(const char *filename, | ||
4962 | const char *attribute, | ||
4963 | Eet_Data_Descriptor *edd, | ||
4964 | const char *cipher_key) | ||
4965 | { | ||
4966 | void *blob; | ||
4967 | void *ret; | ||
4968 | ssize_t size; | ||
4969 | |||
4970 | blob = eina_xattr_get(filename, attribute, &size); | ||
4971 | if (!blob) return NULL; | ||
4972 | |||
4973 | ret = eet_data_descriptor_decode_cipher(edd, blob, cipher_key, size); | ||
4974 | free(blob); | ||
4975 | |||
4976 | return ret; | ||
4977 | } | ||
4978 | |||
4979 | EAPI Eina_Bool | ||
4980 | eet_data_xattr_cipher_set(const char *filename, | ||
4981 | const char *attribute, | ||
4982 | Eet_Data_Descriptor *edd, | ||
4983 | const char *cipher_key, | ||
4984 | const void *data, | ||
4985 | Eina_Xattr_Flags flags) | ||
4986 | { | ||
4987 | void *blob; | ||
4988 | int size; | ||
4989 | Eina_Bool ret; | ||
4990 | |||
4991 | blob = eet_data_descriptor_encode_cipher(edd, data, cipher_key, &size); | ||
4992 | if (!blob) return EINA_FALSE; | ||
4993 | |||
4994 | ret = eina_xattr_set(filename, attribute, blob, size, flags); | ||
4995 | free(blob); | ||
4996 | |||
4997 | return ret; | ||
4998 | } | ||
4999 | |||
diff --git a/libraries/eet/src/lib/eet_dictionary.c b/libraries/eet/src/lib/eet_dictionary.c new file mode 100644 index 0000000..60d0ec1 --- /dev/null +++ b/libraries/eet/src/lib/eet_dictionary.c | |||
@@ -0,0 +1,439 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif /* ifdef HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <stdio.h> | ||
6 | #include <string.h> | ||
7 | #include <math.h> | ||
8 | |||
9 | #include <Eina.h> | ||
10 | |||
11 | #include "Eet.h" | ||
12 | #include "Eet_private.h" | ||
13 | |||
14 | Eet_Dictionary * | ||
15 | eet_dictionary_add(void) | ||
16 | { | ||
17 | Eet_Dictionary *new; | ||
18 | |||
19 | new = calloc(1, sizeof (Eet_Dictionary)); | ||
20 | if (!new) | ||
21 | return NULL; | ||
22 | |||
23 | memset(new->hash, -1, sizeof (int) * 256); | ||
24 | |||
25 | return new; | ||
26 | } /* eet_dictionary_add */ | ||
27 | |||
28 | void | ||
29 | eet_dictionary_free(Eet_Dictionary *ed) | ||
30 | { | ||
31 | if (ed) | ||
32 | { | ||
33 | int i; | ||
34 | |||
35 | for (i = 0; i < ed->count; ++i) | ||
36 | if (ed->all[i].allocated) | ||
37 | eina_stringshare_del(ed->all[i].str); | ||
38 | |||
39 | if (ed->all) | ||
40 | free(ed->all); | ||
41 | |||
42 | if (ed->converts) eina_hash_free(ed->converts); | ||
43 | |||
44 | free(ed); | ||
45 | } | ||
46 | } /* eet_dictionary_free */ | ||
47 | |||
48 | static int | ||
49 | _eet_dictionary_lookup(Eet_Dictionary *ed, | ||
50 | const char *string, | ||
51 | int len, | ||
52 | int hash) | ||
53 | { | ||
54 | Eina_Bool found = EINA_FALSE; | ||
55 | int prev = -1; | ||
56 | int current; | ||
57 | |||
58 | current = ed->hash[hash]; | ||
59 | |||
60 | while (current != -1) | ||
61 | { | ||
62 | if (ed->all[current].len == len) | ||
63 | { | ||
64 | if (ed->all[current].str && | ||
65 | (ed->all[current].str == string || strcmp(ed->all[current].str, string) == 0)) | ||
66 | { | ||
67 | found = EINA_TRUE; | ||
68 | break; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | prev = current; | ||
73 | current = ed->all[current].next; | ||
74 | } | ||
75 | |||
76 | if (current == -1 && found) | ||
77 | return prev; | ||
78 | |||
79 | return current; | ||
80 | } /* _eet_dictionary_lookup */ | ||
81 | |||
82 | int | ||
83 | eet_dictionary_string_add(Eet_Dictionary *ed, | ||
84 | const char *string) | ||
85 | { | ||
86 | Eet_String *current; | ||
87 | const char *str; | ||
88 | int hash; | ||
89 | int idx; | ||
90 | int len; | ||
91 | |||
92 | if (!ed) | ||
93 | return -1; | ||
94 | |||
95 | hash = _eet_hash_gen(string, 8); | ||
96 | len = strlen(string) + 1; | ||
97 | |||
98 | idx = _eet_dictionary_lookup(ed, string, len, hash); | ||
99 | |||
100 | if (idx != -1) | ||
101 | { | ||
102 | if (ed->all[idx].str && (ed->all[idx].str == string || strcmp(ed->all[idx].str, string) == 0)) | ||
103 | return idx; | ||
104 | } | ||
105 | |||
106 | if (ed->total == ed->count) | ||
107 | { | ||
108 | Eet_String *new; | ||
109 | int total; | ||
110 | |||
111 | total = ed->total + 8; | ||
112 | |||
113 | new = realloc(ed->all, sizeof (Eet_String) * total); | ||
114 | if (!new) | ||
115 | return -1; | ||
116 | |||
117 | ed->all = new; | ||
118 | ed->total = total; | ||
119 | } | ||
120 | |||
121 | str = eina_stringshare_add(string); | ||
122 | if (!str) | ||
123 | return -1; | ||
124 | |||
125 | current = ed->all + ed->count; | ||
126 | |||
127 | current->allocated = EINA_TRUE; | ||
128 | |||
129 | current->hash = hash; | ||
130 | |||
131 | current->str = str; | ||
132 | current->len = len; | ||
133 | |||
134 | if (idx == -1) | ||
135 | { | ||
136 | current->next = ed->hash[hash]; | ||
137 | current->prev = -1; | ||
138 | ed->hash[hash] = ed->count; | ||
139 | } | ||
140 | else | ||
141 | { | ||
142 | current->next = idx; | ||
143 | current->prev = ed->all[idx].prev; | ||
144 | |||
145 | if (current->next != -1) | ||
146 | ed->all[current->next].prev = ed->count; | ||
147 | |||
148 | if (current->prev != -1) | ||
149 | ed->all[current->prev].next = ed->count; | ||
150 | else | ||
151 | ed->hash[hash] = ed->count; | ||
152 | } | ||
153 | |||
154 | return ed->count++; | ||
155 | } /* eet_dictionary_string_add */ | ||
156 | |||
157 | int | ||
158 | eet_dictionary_string_get_size(const Eet_Dictionary *ed, | ||
159 | int idx) | ||
160 | { | ||
161 | if (!ed) | ||
162 | return 0; | ||
163 | |||
164 | if (idx < 0) | ||
165 | return 0; | ||
166 | |||
167 | if (idx < ed->count) | ||
168 | return ed->all[idx].len; | ||
169 | |||
170 | return 0; | ||
171 | } /* eet_dictionary_string_get_size */ | ||
172 | |||
173 | int | ||
174 | eet_dictionary_string_get_hash(const Eet_Dictionary *ed, | ||
175 | int idx) | ||
176 | { | ||
177 | if (!ed) | ||
178 | return -1; | ||
179 | |||
180 | if (idx < 0) | ||
181 | return -1; | ||
182 | |||
183 | if (idx < ed->count) | ||
184 | return ed->all[idx].hash; | ||
185 | |||
186 | return -1; | ||
187 | } /* eet_dictionary_string_get_hash */ | ||
188 | |||
189 | const char * | ||
190 | eet_dictionary_string_get_char(const Eet_Dictionary *ed, | ||
191 | int idx) | ||
192 | { | ||
193 | if (!ed) | ||
194 | return NULL; | ||
195 | |||
196 | if (idx < 0) | ||
197 | return NULL; | ||
198 | |||
199 | if (idx < ed->count) | ||
200 | { | ||
201 | #ifdef _WIN32 | ||
202 | /* Windows file system could change the mmaped file when replacing a file. So we need to copy all string in memory to avoid bugs. */ | ||
203 | if (!ed->all[idx].allocated) | ||
204 | { | ||
205 | ed->all[idx].str = eina_stringshare_add(ed->all[idx].str); | ||
206 | ed->all[idx].allocated = EINA_TRUE; | ||
207 | } | ||
208 | #endif /* ifdef _WIN32 */ | ||
209 | return ed->all[idx].str; | ||
210 | } | ||
211 | |||
212 | return NULL; | ||
213 | } /* eet_dictionary_string_get_char */ | ||
214 | |||
215 | static inline Eina_Bool | ||
216 | _eet_dictionary_string_get_me_cache(const char *s, | ||
217 | int len, | ||
218 | int *mantisse, | ||
219 | int *exponent) | ||
220 | { | ||
221 | if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p')) | ||
222 | { | ||
223 | *mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0'); | ||
224 | *exponent = (s[5] - '0'); | ||
225 | |||
226 | return EINA_TRUE; | ||
227 | } | ||
228 | |||
229 | return EINA_FALSE; | ||
230 | } /* _eet_dictionary_string_get_me_cache */ | ||
231 | |||
232 | static inline Eina_Bool | ||
233 | _eet_dictionary_string_get_float_cache(const char *s, | ||
234 | int len, | ||
235 | float *result) | ||
236 | { | ||
237 | int mantisse; | ||
238 | int exponent; | ||
239 | |||
240 | if (_eet_dictionary_string_get_me_cache(s, len, &mantisse, &exponent)) | ||
241 | { | ||
242 | if (s[4] == '+') | ||
243 | *result = (float)(mantisse << exponent); | ||
244 | else | ||
245 | *result = (float)mantisse / (float)(1 << exponent); | ||
246 | |||
247 | return EINA_TRUE; | ||
248 | } | ||
249 | |||
250 | return EINA_FALSE; | ||
251 | } /* _eet_dictionary_string_get_float_cache */ | ||
252 | |||
253 | static inline Eina_Bool | ||
254 | _eet_dictionary_string_get_double_cache(const char *s, | ||
255 | int len, | ||
256 | double *result) | ||
257 | { | ||
258 | int mantisse; | ||
259 | int exponent; | ||
260 | |||
261 | if (_eet_dictionary_string_get_me_cache(s, len, &mantisse, &exponent)) | ||
262 | { | ||
263 | if (s[4] == '+') | ||
264 | *result = (double)(mantisse << exponent); | ||
265 | else | ||
266 | *result = (double)mantisse / (float)(1 << exponent); | ||
267 | |||
268 | return EINA_TRUE; | ||
269 | } | ||
270 | |||
271 | return EINA_FALSE; | ||
272 | } /* _eet_dictionary_string_get_double_cache */ | ||
273 | |||
274 | static inline Eina_Bool | ||
275 | _eet_dictionary_test(const Eet_Dictionary *ed, | ||
276 | int idx, | ||
277 | void *result) | ||
278 | { | ||
279 | if (!result) | ||
280 | return EINA_FALSE; | ||
281 | |||
282 | if (!ed) | ||
283 | return EINA_FALSE; | ||
284 | |||
285 | if (idx < 0) | ||
286 | return EINA_FALSE; | ||
287 | |||
288 | if (!(idx < ed->count)) | ||
289 | return EINA_FALSE; | ||
290 | |||
291 | return EINA_TRUE; | ||
292 | } /* _eet_dictionary_test */ | ||
293 | |||
294 | static Eet_Convert * | ||
295 | eet_dictionary_convert_get(const Eet_Dictionary *ed, | ||
296 | int idx, | ||
297 | const char **str) | ||
298 | { | ||
299 | Eet_Convert *result; | ||
300 | |||
301 | *str = ed->all[idx].str; | ||
302 | |||
303 | if (!ed->converts) | ||
304 | { | ||
305 | ((Eet_Dictionary *)ed)->converts = eina_hash_int32_new(free); | ||
306 | |||
307 | goto add_convert; | ||
308 | } | ||
309 | |||
310 | result = eina_hash_find(ed->converts, &idx); | ||
311 | if (result) return result; | ||
312 | |||
313 | add_convert: | ||
314 | result = calloc(1, sizeof (Eet_Convert)); | ||
315 | |||
316 | eina_hash_add(ed->converts, &idx, result); | ||
317 | return result; | ||
318 | } | ||
319 | |||
320 | Eina_Bool | ||
321 | eet_dictionary_string_get_float(const Eet_Dictionary *ed, | ||
322 | int idx, | ||
323 | float *result) | ||
324 | { | ||
325 | Eet_Convert *convert; | ||
326 | const char *str; | ||
327 | |||
328 | if (!_eet_dictionary_test(ed, idx, result)) | ||
329 | return EINA_FALSE; | ||
330 | |||
331 | convert = eet_dictionary_convert_get(ed, idx, &str); | ||
332 | if (!convert) return EINA_FALSE; | ||
333 | |||
334 | if (!(convert->type & EET_D_FLOAT)) | ||
335 | { | ||
336 | if (!_eet_dictionary_string_get_float_cache(str, ed->all[idx].len, | ||
337 | &convert->f)) | ||
338 | { | ||
339 | long long mantisse = 0; | ||
340 | long exponent = 0; | ||
341 | |||
342 | if (eina_convert_atod(str, ed->all[idx].len, &mantisse, | ||
343 | &exponent) == EINA_FALSE) | ||
344 | return EINA_FALSE; | ||
345 | |||
346 | convert->f = ldexpf((float)mantisse, exponent); | ||
347 | } | ||
348 | |||
349 | convert->type |= EET_D_FLOAT; | ||
350 | } | ||
351 | |||
352 | *result = convert->f; | ||
353 | return EINA_TRUE; | ||
354 | } /* eet_dictionary_string_get_float */ | ||
355 | |||
356 | Eina_Bool | ||
357 | eet_dictionary_string_get_double(const Eet_Dictionary *ed, | ||
358 | int idx, | ||
359 | double *result) | ||
360 | { | ||
361 | Eet_Convert *convert; | ||
362 | const char *str; | ||
363 | |||
364 | if (!_eet_dictionary_test(ed, idx, result)) | ||
365 | return EINA_FALSE; | ||
366 | |||
367 | convert = eet_dictionary_convert_get(ed, idx, &str); | ||
368 | if (!convert) return EINA_FALSE; | ||
369 | |||
370 | if (!(convert->type & EET_D_DOUBLE)) | ||
371 | { | ||
372 | if (!_eet_dictionary_string_get_double_cache(str, ed->all[idx].len, | ||
373 | &convert->d)) | ||
374 | { | ||
375 | long long mantisse = 0; | ||
376 | long exponent = 0; | ||
377 | |||
378 | if (eina_convert_atod(str, ed->all[idx].len, &mantisse, | ||
379 | &exponent) == EINA_FALSE) | ||
380 | return EINA_FALSE; | ||
381 | |||
382 | convert->d = ldexp((double)mantisse, exponent); | ||
383 | } | ||
384 | |||
385 | convert->type |= EET_D_DOUBLE; | ||
386 | } | ||
387 | |||
388 | *result = convert->d; | ||
389 | return EINA_TRUE; | ||
390 | } /* eet_dictionary_string_get_double */ | ||
391 | |||
392 | Eina_Bool | ||
393 | eet_dictionary_string_get_fp(const Eet_Dictionary *ed, | ||
394 | int idx, | ||
395 | Eina_F32p32 *result) | ||
396 | { | ||
397 | Eet_Convert *convert; | ||
398 | const char *str; | ||
399 | |||
400 | if (!_eet_dictionary_test(ed, idx, result)) | ||
401 | return EINA_FALSE; | ||
402 | |||
403 | convert = eet_dictionary_convert_get(ed, idx, &str); | ||
404 | if (!convert) return EINA_FALSE; | ||
405 | |||
406 | if (!(convert->type & EET_D_FIXED_POINT)) | ||
407 | { | ||
408 | Eina_F32p32 fp; | ||
409 | |||
410 | if (!eina_convert_atofp(str, ed->all[idx].len, &fp)) | ||
411 | return EINA_FALSE; | ||
412 | |||
413 | convert->fp = fp; | ||
414 | convert->type |= EET_D_FIXED_POINT; | ||
415 | } | ||
416 | |||
417 | *result = convert->fp; | ||
418 | return EINA_TRUE; | ||
419 | } /* eet_dictionary_string_get_fp */ | ||
420 | |||
421 | EAPI int | ||
422 | eet_dictionary_string_check(Eet_Dictionary *ed, | ||
423 | const char *string) | ||
424 | { | ||
425 | int i; | ||
426 | |||
427 | if ((!ed) || (!string)) | ||
428 | return 0; | ||
429 | |||
430 | if ((ed->start <= string) && (string < ed->end)) | ||
431 | return 1; | ||
432 | |||
433 | for (i = 0; i < ed->count; ++i) | ||
434 | if ((ed->all[i].allocated) && ed->all[i].str == string) | ||
435 | return 1; | ||
436 | |||
437 | return 0; | ||
438 | } /* eet_dictionary_string_check */ | ||
439 | |||
diff --git a/libraries/eet/src/lib/eet_image.c b/libraries/eet/src/lib/eet_image.c new file mode 100644 index 0000000..79f6f90 --- /dev/null +++ b/libraries/eet/src/lib/eet_image.c | |||
@@ -0,0 +1,1820 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif /* ifdef HAVE_CONFIG_H */ | ||
4 | |||
5 | #ifdef HAVE_ALLOCA_H | ||
6 | # include <alloca.h> | ||
7 | #elif defined __GNUC__ | ||
8 | # define alloca __builtin_alloca | ||
9 | #elif defined _AIX | ||
10 | # define alloca __alloca | ||
11 | #elif defined _MSC_VER | ||
12 | # include <malloc.h> | ||
13 | # define alloca _alloca | ||
14 | #else /* ifdef HAVE_ALLOCA_H */ | ||
15 | # include <stddef.h> | ||
16 | # ifdef __cplusplus | ||
17 | extern "C" | ||
18 | # endif /* ifdef __cplusplus */ | ||
19 | void *alloca(size_t); | ||
20 | #endif /* ifdef HAVE_ALLOCA_H */ | ||
21 | |||
22 | #ifdef HAVE_NETINET_IN_H | ||
23 | # ifdef __OpenBSD__ | ||
24 | # include <sys/types.h> | ||
25 | # endif /* ifdef __OpenBSD__ */ | ||
26 | # include <netinet/in.h> | ||
27 | #endif /* ifdef HAVE_NETINET_IN_H */ | ||
28 | |||
29 | #ifdef _WIN32 | ||
30 | # include <winsock2.h> | ||
31 | # define HAVE_BOOLEAN | ||
32 | #endif /* ifdef _WIN32 */ | ||
33 | |||
34 | #include <stdio.h> | ||
35 | #include <string.h> | ||
36 | #include <setjmp.h> | ||
37 | #include <zlib.h> | ||
38 | #include <jpeglib.h> | ||
39 | |||
40 | #include "Eet.h" | ||
41 | #include "Eet_private.h" | ||
42 | |||
43 | /*---*/ | ||
44 | |||
45 | typedef struct _JPEG_error_mgr *emptr; | ||
46 | |||
47 | /*---*/ | ||
48 | |||
49 | struct _JPEG_error_mgr | ||
50 | { | ||
51 | struct jpeg_error_mgr pub; | ||
52 | jmp_buf setjmp_buffer; | ||
53 | }; | ||
54 | |||
55 | struct jpeg_membuf_src | ||
56 | { | ||
57 | struct jpeg_source_mgr pub; | ||
58 | |||
59 | const unsigned char *buf; | ||
60 | size_t len; | ||
61 | struct jpeg_membuf_src *self; | ||
62 | }; | ||
63 | |||
64 | static void | ||
65 | _eet_jpeg_membuf_src_init(j_decompress_ptr cinfo) | ||
66 | { | ||
67 | /* FIXME: Use attribute unused */ | ||
68 | (void)cinfo; | ||
69 | } /* _eet_jpeg_membuf_src_init */ | ||
70 | |||
71 | static boolean | ||
72 | _eet_jpeg_membuf_src_fill(j_decompress_ptr cinfo) | ||
73 | { | ||
74 | static const JOCTET jpeg_eoi[2] = { 0xFF, JPEG_EOI }; | ||
75 | struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src; | ||
76 | |||
77 | src->pub.bytes_in_buffer = sizeof(jpeg_eoi); | ||
78 | src->pub.next_input_byte = jpeg_eoi; | ||
79 | |||
80 | return TRUE; | ||
81 | } /* _eet_jpeg_membuf_src_fill */ | ||
82 | |||
83 | static void | ||
84 | _eet_jpeg_membuf_src_skip(j_decompress_ptr cinfo, | ||
85 | long num_bytes) | ||
86 | { | ||
87 | struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src; | ||
88 | |||
89 | src->pub.bytes_in_buffer -= num_bytes; | ||
90 | src->pub.next_input_byte += num_bytes; | ||
91 | } /* _eet_jpeg_membuf_src_skip */ | ||
92 | |||
93 | static void | ||
94 | _eet_jpeg_membuf_src_term(j_decompress_ptr cinfo) | ||
95 | { | ||
96 | struct jpeg_membuf_src *src = ((struct jpeg_membuf_src *)cinfo->src)->self; | ||
97 | |||
98 | free(src); | ||
99 | cinfo->src = NULL; | ||
100 | } /* _eet_jpeg_membuf_src_term */ | ||
101 | |||
102 | static int | ||
103 | eet_jpeg_membuf_src(j_decompress_ptr cinfo, | ||
104 | const void *buf, | ||
105 | size_t len) | ||
106 | { | ||
107 | struct jpeg_membuf_src *src; | ||
108 | |||
109 | src = calloc(1, sizeof(*src)); | ||
110 | if (!src) | ||
111 | return -1; | ||
112 | |||
113 | src->self = src; | ||
114 | |||
115 | cinfo->src = &src->pub; | ||
116 | src->buf = buf; | ||
117 | src->len = len; | ||
118 | src->pub.init_source = _eet_jpeg_membuf_src_init; | ||
119 | src->pub.fill_input_buffer = _eet_jpeg_membuf_src_fill; | ||
120 | src->pub.skip_input_data = _eet_jpeg_membuf_src_skip; | ||
121 | src->pub.resync_to_restart = jpeg_resync_to_restart; | ||
122 | src->pub.term_source = _eet_jpeg_membuf_src_term; | ||
123 | src->pub.bytes_in_buffer = src->len; | ||
124 | src->pub.next_input_byte = src->buf; | ||
125 | |||
126 | return 0; | ||
127 | } /* eet_jpeg_membuf_src */ | ||
128 | |||
129 | struct jpeg_membuf_dst | ||
130 | { | ||
131 | struct jpeg_destination_mgr pub; | ||
132 | |||
133 | void **dst_buf; | ||
134 | size_t *dst_len; | ||
135 | |||
136 | unsigned char *buf; | ||
137 | size_t len; | ||
138 | int failed; | ||
139 | struct jpeg_membuf_dst *self; | ||
140 | }; | ||
141 | |||
142 | static void | ||
143 | _eet_jpeg_membuf_dst_init(j_compress_ptr cinfo) | ||
144 | { | ||
145 | /* FIXME: Use eina attribute */ | ||
146 | (void)cinfo; | ||
147 | } /* _eet_jpeg_membuf_dst_init */ | ||
148 | |||
149 | static boolean | ||
150 | _eet_jpeg_membuf_dst_flush(j_compress_ptr cinfo) | ||
151 | { | ||
152 | struct jpeg_membuf_dst *dst = (struct jpeg_membuf_dst *)cinfo->dest; | ||
153 | unsigned char *buf; | ||
154 | |||
155 | if (dst->len >= 0x40000000 || | ||
156 | !(buf = realloc(dst->buf, dst->len * 2))) | ||
157 | { | ||
158 | dst->failed = 1; | ||
159 | dst->pub.next_output_byte = dst->buf; | ||
160 | dst->pub.free_in_buffer = dst->len; | ||
161 | return TRUE; | ||
162 | } | ||
163 | |||
164 | dst->pub.next_output_byte = | ||
165 | buf + ((unsigned char *)dst->pub.next_output_byte - dst->buf); | ||
166 | dst->buf = buf; | ||
167 | dst->pub.free_in_buffer += dst->len; | ||
168 | dst->len *= 2; | ||
169 | |||
170 | return FALSE; | ||
171 | } /* _eet_jpeg_membuf_dst_flush */ | ||
172 | |||
173 | static void | ||
174 | _eet_jpeg_membuf_dst_term(j_compress_ptr cinfo) | ||
175 | { | ||
176 | struct jpeg_membuf_dst *dst = ((struct jpeg_membuf_dst *)cinfo->dest)->self; | ||
177 | |||
178 | if (dst->failed) | ||
179 | { | ||
180 | *dst->dst_buf = NULL; | ||
181 | *dst->dst_len = 0; | ||
182 | free(dst->buf); | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | *dst->dst_buf = dst->buf; | ||
187 | *dst->dst_len = (unsigned char *)dst->pub.next_output_byte - dst->buf; | ||
188 | } | ||
189 | |||
190 | free(dst); | ||
191 | cinfo->dest = NULL; | ||
192 | } /* _eet_jpeg_membuf_dst_term */ | ||
193 | |||
194 | static int | ||
195 | eet_jpeg_membuf_dst(j_compress_ptr cinfo, | ||
196 | void **buf, | ||
197 | size_t *len) | ||
198 | { | ||
199 | struct jpeg_membuf_dst *dst; | ||
200 | |||
201 | dst = calloc(1, sizeof(*dst)); | ||
202 | if (!dst) | ||
203 | return -1; | ||
204 | |||
205 | dst->buf = malloc(32768); | ||
206 | if (!dst->buf) | ||
207 | { | ||
208 | free(dst); | ||
209 | return -1; | ||
210 | } | ||
211 | |||
212 | dst->self = dst; | ||
213 | dst->len = 32768; | ||
214 | |||
215 | cinfo->dest = &dst->pub; | ||
216 | dst->pub.init_destination = _eet_jpeg_membuf_dst_init; | ||
217 | dst->pub.empty_output_buffer = _eet_jpeg_membuf_dst_flush; | ||
218 | dst->pub.term_destination = _eet_jpeg_membuf_dst_term; | ||
219 | dst->pub.free_in_buffer = dst->len; | ||
220 | dst->pub.next_output_byte = dst->buf; | ||
221 | dst->dst_buf = buf; | ||
222 | dst->dst_len = len; | ||
223 | dst->failed = 0; | ||
224 | |||
225 | return 0; | ||
226 | } /* eet_jpeg_membuf_dst */ | ||
227 | |||
228 | /*---*/ | ||
229 | |||
230 | static void _JPEGFatalErrorHandler(j_common_ptr cinfo); | ||
231 | static void _JPEGErrorHandler(j_common_ptr cinfo); | ||
232 | static void _JPEGErrorHandler2(j_common_ptr cinfo, | ||
233 | int msg_level); | ||
234 | |||
235 | static int | ||
236 | eet_data_image_jpeg_header_decode(const void *data, | ||
237 | int size, | ||
238 | unsigned int *w, | ||
239 | unsigned int *h); | ||
240 | static int | ||
241 | eet_data_image_jpeg_rgb_decode(const void *data, | ||
242 | int size, | ||
243 | unsigned int src_x, | ||
244 | unsigned int src_y, | ||
245 | unsigned int *d, | ||
246 | unsigned int w, | ||
247 | unsigned int h, | ||
248 | unsigned int row_stride); | ||
249 | static void * | ||
250 | eet_data_image_jpeg_alpha_decode(const void *data, | ||
251 | int size, | ||
252 | unsigned int src_x, | ||
253 | unsigned int src_y, | ||
254 | unsigned int *d, | ||
255 | unsigned int w, | ||
256 | unsigned int h, | ||
257 | unsigned int row_stride); | ||
258 | static void * | ||
259 | eet_data_image_lossless_convert(int *size, | ||
260 | const void *data, | ||
261 | unsigned int w, | ||
262 | unsigned int h, | ||
263 | int alpha); | ||
264 | static void * | ||
265 | eet_data_image_lossless_compressed_convert(int *size, | ||
266 | const void *data, | ||
267 | unsigned int w, | ||
268 | unsigned int h, | ||
269 | int alpha, | ||
270 | int compression); | ||
271 | static void * | ||
272 | eet_data_image_jpeg_convert(int *size, | ||
273 | const void *data, | ||
274 | unsigned int w, | ||
275 | unsigned int h, | ||
276 | int alpha, | ||
277 | int quality); | ||
278 | static void * | ||
279 | eet_data_image_jpeg_alpha_convert(int *size, | ||
280 | const void *data, | ||
281 | unsigned int w, | ||
282 | unsigned int h, | ||
283 | int alpha, | ||
284 | int quality); | ||
285 | |||
286 | /*---*/ | ||
287 | |||
288 | static int _eet_image_words_bigendian = -1; | ||
289 | |||
290 | /*---*/ | ||
291 | |||
292 | #define SWAP64(x) (x) = \ | ||
293 | ((((unsigned long long)(x) & 0x00000000000000ffULL) << 56) | \ | ||
294 | (((unsigned long long)(x) & 0x000000000000ff00ULL) << 40) | \ | ||
295 | (((unsigned long long)(x) & 0x0000000000ff0000ULL) << 24) | \ | ||
296 | (((unsigned long long)(x) & 0x00000000ff000000ULL) << 8) | \ | ||
297 | (((unsigned long long)(x) & 0x000000ff00000000ULL) >> 8) | \ | ||
298 | (((unsigned long long)(x) & 0x0000ff0000000000ULL) >> 24) | \ | ||
299 | (((unsigned long long)(x) & 0x00ff000000000000ULL) >> 40) | \ | ||
300 | (((unsigned long long)(x) & 0xff00000000000000ULL) >> 56)) | ||
301 | #define SWAP32(x) (x) = \ | ||
302 | ((((int)(x) & 0x000000ff) << 24) | \ | ||
303 | (((int)(x) & 0x0000ff00) << 8) | \ | ||
304 | (((int)(x) & 0x00ff0000) >> 8) | \ | ||
305 | (((int)(x) & 0xff000000) >> 24)) | ||
306 | #define SWAP16(x) (x) = \ | ||
307 | ((((short)(x) & 0x00ff) << 8) | \ | ||
308 | (((short)(x) & 0xff00) >> 8)) | ||
309 | |||
310 | #ifdef CONV8 | ||
311 | # undef CONV8 | ||
312 | #endif /* ifdef CONV8 */ | ||
313 | #ifdef CONV16 | ||
314 | # undef CONV16 | ||
315 | #endif /* ifdef CONV16 */ | ||
316 | #ifdef CONV32 | ||
317 | # undef CONV32 | ||
318 | #endif /* ifdef CONV32 */ | ||
319 | #ifdef CONV64 | ||
320 | # undef CONV64 | ||
321 | #endif /* ifdef CONV64 */ | ||
322 | |||
323 | #define CONV8(x) | ||
324 | #define CONV16(x) {if (_eet_image_words_bigendian) {SWAP16(x); }} | ||
325 | #define CONV32(x) {if (_eet_image_words_bigendian) {SWAP32(x); }} | ||
326 | #define CONV64(x) {if (_eet_image_words_bigendian) {SWAP64(x); }} | ||
327 | |||
328 | /*---*/ | ||
329 | |||
330 | static void | ||
331 | _JPEGFatalErrorHandler(j_common_ptr cinfo) | ||
332 | { | ||
333 | emptr errmgr; | ||
334 | |||
335 | errmgr = (emptr)cinfo->err; | ||
336 | /* cinfo->err->output_message(cinfo);*/ | ||
337 | longjmp(errmgr->setjmp_buffer, 1); | ||
338 | return; | ||
339 | } /* _JPEGFatalErrorHandler */ | ||
340 | |||
341 | static void | ||
342 | _JPEGErrorHandler(j_common_ptr cinfo __UNUSED__) | ||
343 | { | ||
344 | /* emptr errmgr; */ | ||
345 | |||
346 | /* errmgr = (emptr) cinfo->err; */ | ||
347 | /* cinfo->err->output_message(cinfo);*/ | ||
348 | /* longjmp(errmgr->setjmp_buffer, 1);*/ | ||
349 | return; | ||
350 | } /* _JPEGErrorHandler */ | ||
351 | |||
352 | static void | ||
353 | _JPEGErrorHandler2(j_common_ptr cinfo __UNUSED__, | ||
354 | int msg_level __UNUSED__) | ||
355 | { | ||
356 | /* emptr errmgr; */ | ||
357 | |||
358 | /* errmgr = (emptr) cinfo->err; */ | ||
359 | /* cinfo->err->output_message(cinfo);*/ | ||
360 | /* longjmp(errmgr->setjmp_buffer, 1);*/ | ||
361 | return; | ||
362 | } /* _JPEGErrorHandler2 */ | ||
363 | |||
364 | static int | ||
365 | eet_data_image_jpeg_header_decode(const void *data, | ||
366 | int size, | ||
367 | unsigned int *w, | ||
368 | unsigned int *h) | ||
369 | { | ||
370 | struct jpeg_decompress_struct cinfo; | ||
371 | struct _JPEG_error_mgr jerr; | ||
372 | |||
373 | memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct)); | ||
374 | |||
375 | cinfo.err = jpeg_std_error(&(jerr.pub)); | ||
376 | jerr.pub.error_exit = _JPEGFatalErrorHandler; | ||
377 | jerr.pub.emit_message = _JPEGErrorHandler2; | ||
378 | jerr.pub.output_message = _JPEGErrorHandler; | ||
379 | if (setjmp(jerr.setjmp_buffer)) | ||
380 | return 0; | ||
381 | |||
382 | jpeg_create_decompress(&cinfo); | ||
383 | |||
384 | if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size)) | ||
385 | { | ||
386 | jpeg_destroy_decompress(&cinfo); | ||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | jpeg_read_header(&cinfo, TRUE); | ||
391 | cinfo.do_fancy_upsampling = FALSE; | ||
392 | cinfo.do_block_smoothing = FALSE; | ||
393 | jpeg_start_decompress(&cinfo); | ||
394 | |||
395 | /* head decoding */ | ||
396 | *w = cinfo.output_width; | ||
397 | *h = cinfo.output_height; | ||
398 | |||
399 | free(cinfo.src); | ||
400 | cinfo.src = NULL; | ||
401 | |||
402 | jpeg_destroy_decompress(&cinfo); | ||
403 | |||
404 | if ((*w < 1) || (*h < 1) || (*w > 8192) || (*h > 8192)) | ||
405 | return 0; | ||
406 | |||
407 | return 1; | ||
408 | } /* eet_data_image_jpeg_header_decode */ | ||
409 | |||
410 | static int | ||
411 | eet_data_image_jpeg_rgb_decode(const void *data, | ||
412 | int size, | ||
413 | unsigned int src_x, | ||
414 | unsigned int src_y, | ||
415 | unsigned int *d, | ||
416 | unsigned int w, | ||
417 | unsigned int h, | ||
418 | unsigned int row_stride) | ||
419 | { | ||
420 | struct jpeg_decompress_struct cinfo; | ||
421 | struct _JPEG_error_mgr jerr; | ||
422 | unsigned char *ptr, *line[16], *tdata = NULL; | ||
423 | unsigned int *ptr2, *tmp; | ||
424 | unsigned int iw, ih; | ||
425 | unsigned int x, y, l, scans; | ||
426 | unsigned int i; | ||
427 | |||
428 | /* FIXME: handle src_x, src_y and row_stride correctly */ | ||
429 | if (!d) | ||
430 | return 0; | ||
431 | |||
432 | memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct)); | ||
433 | |||
434 | cinfo.err = jpeg_std_error(&(jerr.pub)); | ||
435 | jerr.pub.error_exit = _JPEGFatalErrorHandler; | ||
436 | jerr.pub.emit_message = _JPEGErrorHandler2; | ||
437 | jerr.pub.output_message = _JPEGErrorHandler; | ||
438 | if (setjmp(jerr.setjmp_buffer)) | ||
439 | return 0; | ||
440 | |||
441 | jpeg_create_decompress(&cinfo); | ||
442 | |||
443 | if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size)) | ||
444 | { | ||
445 | jpeg_destroy_decompress(&cinfo); | ||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | jpeg_read_header(&cinfo, TRUE); | ||
450 | cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss) | ||
451 | cinfo.do_fancy_upsampling = FALSE; | ||
452 | cinfo.do_block_smoothing = FALSE; | ||
453 | jpeg_start_decompress(&cinfo); | ||
454 | |||
455 | /* head decoding */ | ||
456 | iw = cinfo.output_width; | ||
457 | ih = cinfo.output_height; | ||
458 | if ((iw != w) || (ih != h)) | ||
459 | { | ||
460 | free(cinfo.src); | ||
461 | cinfo.src = NULL; | ||
462 | |||
463 | jpeg_destroy_decompress(&cinfo); | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | /* end head decoding */ | ||
468 | /* data decoding */ | ||
469 | if (cinfo.rec_outbuf_height > 16) | ||
470 | { | ||
471 | free(cinfo.src); | ||
472 | cinfo.src = NULL; | ||
473 | |||
474 | jpeg_destroy_decompress(&cinfo); | ||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | tdata = alloca((iw) * 16 * 3); | ||
479 | ptr2 = d; | ||
480 | |||
481 | if (cinfo.output_components == 3) | ||
482 | { | ||
483 | for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++) | ||
484 | line[i] = tdata + (i * (iw) * 3); | ||
485 | for (l = 0; l < ih; l += cinfo.rec_outbuf_height) | ||
486 | { | ||
487 | jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); | ||
488 | scans = cinfo.rec_outbuf_height; | ||
489 | if ((ih - l) < scans) | ||
490 | scans = ih - l; | ||
491 | |||
492 | ptr = tdata; | ||
493 | |||
494 | if (l + scans >= src_y && l < src_y + h) | ||
495 | { | ||
496 | y = src_y - l; | ||
497 | if (src_y < l) | ||
498 | y = 0; | ||
499 | |||
500 | for (ptr += 3 * iw * y; y < scans && (y + l) < (src_y + h); | ||
501 | y++) | ||
502 | { | ||
503 | tmp = ptr2; | ||
504 | ptr += 3 * src_x; | ||
505 | for (x = 0; x < w; x++) | ||
506 | { | ||
507 | *ptr2 = | ||
508 | (0xff000000) | | ||
509 | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]); | ||
510 | ptr += 3; | ||
511 | ptr2++; | ||
512 | } | ||
513 | ptr += 3 * (iw - w); | ||
514 | ptr2 = tmp + row_stride / 4; | ||
515 | } | ||
516 | } | ||
517 | } | ||
518 | } | ||
519 | else if (cinfo.output_components == 1) | ||
520 | { | ||
521 | for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++) | ||
522 | line[i] = tdata + (i * (iw)); | ||
523 | for (l = 0; l < (ih); l += cinfo.rec_outbuf_height) | ||
524 | { | ||
525 | jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); | ||
526 | scans = cinfo.rec_outbuf_height; | ||
527 | if (((ih) - l) < scans) | ||
528 | scans = (ih) - l; | ||
529 | |||
530 | ptr = tdata; | ||
531 | |||
532 | if (l >= src_y && l < src_y + h) | ||
533 | { | ||
534 | y = src_y - l; | ||
535 | if (src_y < l) | ||
536 | y = 0; | ||
537 | |||
538 | for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++) | ||
539 | { | ||
540 | tmp = ptr2; | ||
541 | ptr += src_x; | ||
542 | for (x = 0; x < w; x++) | ||
543 | { | ||
544 | *ptr2 = | ||
545 | (0xff000000) | | ||
546 | ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]); | ||
547 | ptr++; | ||
548 | ptr2++; | ||
549 | } | ||
550 | ptr += iw - w; | ||
551 | ptr2 = tmp + row_stride / 4; | ||
552 | } | ||
553 | } | ||
554 | } | ||
555 | } | ||
556 | |||
557 | /* end data decoding */ | ||
558 | jpeg_finish_decompress(&cinfo); | ||
559 | jpeg_destroy_decompress(&cinfo); | ||
560 | return 1; | ||
561 | } /* eet_data_image_jpeg_rgb_decode */ | ||
562 | |||
563 | static void * | ||
564 | eet_data_image_jpeg_alpha_decode(const void *data, | ||
565 | int size, | ||
566 | unsigned int src_x, | ||
567 | unsigned int src_y, | ||
568 | unsigned int *d, | ||
569 | unsigned int w, | ||
570 | unsigned int h, | ||
571 | unsigned int row_stride) | ||
572 | { | ||
573 | struct jpeg_decompress_struct cinfo; | ||
574 | struct _JPEG_error_mgr jerr; | ||
575 | unsigned char *ptr, *line[16], *tdata = NULL; | ||
576 | unsigned int *ptr2, *tmp; | ||
577 | unsigned int x, y, l, scans; | ||
578 | unsigned int i, iw; | ||
579 | |||
580 | memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct)); | ||
581 | |||
582 | cinfo.err = jpeg_std_error(&(jerr.pub)); | ||
583 | jerr.pub.error_exit = _JPEGFatalErrorHandler; | ||
584 | jerr.pub.emit_message = _JPEGErrorHandler2; | ||
585 | jerr.pub.output_message = _JPEGErrorHandler; | ||
586 | if (setjmp(jerr.setjmp_buffer)) | ||
587 | return NULL; | ||
588 | |||
589 | jpeg_create_decompress(&cinfo); | ||
590 | |||
591 | if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size)) | ||
592 | { | ||
593 | jpeg_destroy_decompress(&cinfo); | ||
594 | return NULL; | ||
595 | } | ||
596 | |||
597 | jpeg_read_header(&cinfo, TRUE); | ||
598 | cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss) | ||
599 | cinfo.do_fancy_upsampling = FALSE; | ||
600 | cinfo.do_block_smoothing = FALSE; | ||
601 | jpeg_start_decompress(&cinfo); | ||
602 | |||
603 | /* head decoding */ | ||
604 | iw = cinfo.output_width; | ||
605 | if (w != cinfo.output_width | ||
606 | || h != cinfo.output_height) | ||
607 | { | ||
608 | free(cinfo.src); | ||
609 | cinfo.src = NULL; | ||
610 | |||
611 | jpeg_destroy_decompress(&cinfo); | ||
612 | return NULL; | ||
613 | } | ||
614 | |||
615 | /* end head decoding */ | ||
616 | /* data decoding */ | ||
617 | if (cinfo.rec_outbuf_height > 16) | ||
618 | { | ||
619 | free(cinfo.src); | ||
620 | cinfo.src = NULL; | ||
621 | |||
622 | jpeg_destroy_decompress(&cinfo); | ||
623 | return NULL; | ||
624 | } | ||
625 | |||
626 | tdata = alloca(w * 16 * 3); | ||
627 | ptr2 = d; | ||
628 | if (cinfo.output_components == 1) | ||
629 | { | ||
630 | for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++) | ||
631 | line[i] = tdata + (i * w); | ||
632 | for (l = 0; l < h; l += cinfo.rec_outbuf_height) | ||
633 | { | ||
634 | jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); | ||
635 | scans = cinfo.rec_outbuf_height; | ||
636 | if ((h - l) < scans) | ||
637 | scans = h - l; | ||
638 | |||
639 | ptr = tdata; | ||
640 | |||
641 | if (l >= src_y && l < src_y + h) | ||
642 | { | ||
643 | y = src_y - l; | ||
644 | if (src_y < l) | ||
645 | y = 0; | ||
646 | |||
647 | for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++) | ||
648 | { | ||
649 | tmp = ptr2; | ||
650 | ptr += src_x; | ||
651 | for (x = 0; x < w; x++) | ||
652 | { | ||
653 | *ptr2 = | ||
654 | ((*ptr2) & 0x00ffffff) | | ||
655 | ((ptr[0]) << 24); | ||
656 | ptr++; | ||
657 | ptr2++; | ||
658 | } | ||
659 | ptr += iw - w; | ||
660 | ptr2 = tmp + row_stride / 4; | ||
661 | } | ||
662 | } | ||
663 | } | ||
664 | } | ||
665 | |||
666 | /* end data decoding */ | ||
667 | jpeg_finish_decompress(&cinfo); | ||
668 | jpeg_destroy_decompress(&cinfo); | ||
669 | return d; | ||
670 | } /* eet_data_image_jpeg_alpha_decode */ | ||
671 | |||
672 | static void * | ||
673 | eet_data_image_lossless_convert(int *size, | ||
674 | const void *data, | ||
675 | unsigned int w, | ||
676 | unsigned int h, | ||
677 | int alpha) | ||
678 | { | ||
679 | if (_eet_image_words_bigendian == -1) | ||
680 | { | ||
681 | unsigned long int v; | ||
682 | |||
683 | v = htonl(0x12345678); | ||
684 | if (v == 0x12345678) | ||
685 | _eet_image_words_bigendian = 1; | ||
686 | else | ||
687 | _eet_image_words_bigendian = 0; | ||
688 | } | ||
689 | |||
690 | { | ||
691 | unsigned char *d; | ||
692 | int *header; | ||
693 | |||
694 | d = malloc((w * h * 4) + (8 * 4)); | ||
695 | if (!d) | ||
696 | return NULL; | ||
697 | |||
698 | header = (int *)d; | ||
699 | memset(d, 0, 32); | ||
700 | |||
701 | header[0] = 0xac1dfeed; | ||
702 | header[1] = w; | ||
703 | header[2] = h; | ||
704 | header[3] = alpha; | ||
705 | |||
706 | memcpy(d + 32, data, w * h * 4); | ||
707 | |||
708 | if (_eet_image_words_bigendian) | ||
709 | { | ||
710 | unsigned int i; | ||
711 | |||
712 | for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]); | ||
713 | } | ||
714 | |||
715 | *size = ((w * h * 4) + (8 * 4)); | ||
716 | return d; | ||
717 | } | ||
718 | } /* eet_data_image_lossless_convert */ | ||
719 | |||
720 | static void * | ||
721 | eet_data_image_lossless_compressed_convert(int *size, | ||
722 | const void *data, | ||
723 | unsigned int w, | ||
724 | unsigned int h, | ||
725 | int alpha, | ||
726 | int compression) | ||
727 | { | ||
728 | if (_eet_image_words_bigendian == -1) | ||
729 | { | ||
730 | unsigned long int v; | ||
731 | |||
732 | v = htonl(0x12345678); | ||
733 | if (v == 0x12345678) | ||
734 | _eet_image_words_bigendian = 1; | ||
735 | else | ||
736 | _eet_image_words_bigendian = 0; | ||
737 | } | ||
738 | |||
739 | { | ||
740 | unsigned char *d; | ||
741 | unsigned char *comp; | ||
742 | int *header; | ||
743 | int ret; | ||
744 | uLongf buflen; | ||
745 | |||
746 | d = malloc((w * h * 4) + (8 * 4)); | ||
747 | if (!d) | ||
748 | return NULL; | ||
749 | |||
750 | buflen = (((w * h * 101) / 100) + 3) * 4; | ||
751 | comp = malloc(buflen); | ||
752 | if (!comp) | ||
753 | { | ||
754 | free(d); | ||
755 | return NULL; | ||
756 | } | ||
757 | |||
758 | header = (int *)d; | ||
759 | memset(d, 0, 32); | ||
760 | |||
761 | header[0] = 0xac1dfeed; | ||
762 | header[1] = w; | ||
763 | header[2] = h; | ||
764 | header[3] = alpha; | ||
765 | header[4] = compression; | ||
766 | memcpy(d + 32, data, w * h * 4); | ||
767 | |||
768 | if (_eet_image_words_bigendian) | ||
769 | { | ||
770 | unsigned int i; | ||
771 | |||
772 | for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]); | ||
773 | } | ||
774 | |||
775 | ret = compress2((Bytef *)comp, &buflen, | ||
776 | (Bytef *)(d + 32), | ||
777 | (uLong)(w * h * 4), | ||
778 | compression); | ||
779 | if (ret != Z_OK || buflen > (w * h * 4)) | ||
780 | { | ||
781 | free(comp); | ||
782 | free(d); | ||
783 | *size = -1; | ||
784 | return NULL; | ||
785 | } | ||
786 | |||
787 | memcpy(d + 32, comp, buflen); | ||
788 | *size = (8 * 4) + buflen; | ||
789 | free(comp); | ||
790 | return d; | ||
791 | } | ||
792 | } /* eet_data_image_lossless_compressed_convert */ | ||
793 | |||
794 | static void * | ||
795 | eet_data_image_jpeg_convert(int *size, | ||
796 | const void *data, | ||
797 | unsigned int w, | ||
798 | unsigned int h, | ||
799 | int alpha, | ||
800 | int quality) | ||
801 | { | ||
802 | struct jpeg_compress_struct cinfo; | ||
803 | struct _JPEG_error_mgr jerr; | ||
804 | const int *ptr; | ||
805 | void *d = NULL; | ||
806 | size_t sz = 0; | ||
807 | JSAMPROW *jbuf; | ||
808 | unsigned char *buf; | ||
809 | |||
810 | (void)alpha; /* unused */ | ||
811 | |||
812 | buf = alloca(3 * w); | ||
813 | |||
814 | memset(&cinfo, 0, sizeof (struct jpeg_compress_struct)); | ||
815 | |||
816 | cinfo.err = jpeg_std_error(&(jerr.pub)); | ||
817 | jerr.pub.error_exit = _JPEGFatalErrorHandler; | ||
818 | jerr.pub.emit_message = _JPEGErrorHandler2; | ||
819 | jerr.pub.output_message = _JPEGErrorHandler; | ||
820 | if (setjmp(jerr.setjmp_buffer)) | ||
821 | return NULL; | ||
822 | |||
823 | jpeg_create_compress(&cinfo); | ||
824 | |||
825 | if (eet_jpeg_membuf_dst(&cinfo, &d, &sz)) | ||
826 | { | ||
827 | jpeg_destroy_compress(&cinfo); | ||
828 | return NULL; | ||
829 | } | ||
830 | |||
831 | cinfo.image_width = w; | ||
832 | cinfo.image_height = h; | ||
833 | cinfo.input_components = 3; | ||
834 | cinfo.in_color_space = JCS_RGB; | ||
835 | cinfo.optimize_coding = FALSE; | ||
836 | cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss) | ||
837 | if (quality < 60) cinfo.dct_method = JDCT_IFAST; | ||
838 | jpeg_set_defaults(&cinfo); | ||
839 | jpeg_set_quality(&cinfo, quality, TRUE); | ||
840 | |||
841 | if (quality >= 90) | ||
842 | { | ||
843 | cinfo.comp_info[0].h_samp_factor = 1; | ||
844 | cinfo.comp_info[0].v_samp_factor = 1; | ||
845 | cinfo.comp_info[1].h_samp_factor = 1; | ||
846 | cinfo.comp_info[1].v_samp_factor = 1; | ||
847 | cinfo.comp_info[2].h_samp_factor = 1; | ||
848 | cinfo.comp_info[2].v_samp_factor = 1; | ||
849 | } | ||
850 | |||
851 | jpeg_start_compress(&cinfo, TRUE); | ||
852 | |||
853 | while (cinfo.next_scanline < cinfo.image_height) | ||
854 | { | ||
855 | unsigned int i, j; | ||
856 | |||
857 | /* convert scaline from ARGB to RGB packed */ | ||
858 | ptr = ((const int *)data) + cinfo.next_scanline * w; | ||
859 | for (j = 0, i = 0; i < w; i++) | ||
860 | { | ||
861 | buf[j++] = ((*ptr) >> 16) & 0xff; | ||
862 | buf[j++] = ((*ptr) >> 8) & 0xff; | ||
863 | buf[j++] = ((*ptr)) & 0xff; | ||
864 | ptr++; | ||
865 | } | ||
866 | jbuf = (JSAMPROW *)(&buf); | ||
867 | jpeg_write_scanlines(&cinfo, jbuf, 1); | ||
868 | } | ||
869 | |||
870 | jpeg_finish_compress(&cinfo); | ||
871 | jpeg_destroy_compress(&cinfo); | ||
872 | |||
873 | *size = sz; | ||
874 | return d; | ||
875 | } /* eet_data_image_jpeg_convert */ | ||
876 | |||
877 | static void * | ||
878 | eet_data_image_jpeg_alpha_convert(int *size, | ||
879 | const void *data, | ||
880 | unsigned int w, | ||
881 | unsigned int h, | ||
882 | int alpha, | ||
883 | int quality) | ||
884 | { | ||
885 | unsigned char *d1, *d2; | ||
886 | unsigned char *d; | ||
887 | int *header; | ||
888 | int sz1, sz2; | ||
889 | |||
890 | (void)alpha; /* unused */ | ||
891 | |||
892 | if (_eet_image_words_bigendian == -1) | ||
893 | { | ||
894 | unsigned long int v; | ||
895 | |||
896 | v = htonl(0x12345678); | ||
897 | if (v == 0x12345678) | ||
898 | _eet_image_words_bigendian = 1; | ||
899 | else | ||
900 | _eet_image_words_bigendian = 0; | ||
901 | } | ||
902 | |||
903 | { | ||
904 | const int *ptr; | ||
905 | void *dst = NULL; | ||
906 | size_t sz = 0; | ||
907 | struct _JPEG_error_mgr jerr; | ||
908 | JSAMPROW *jbuf; | ||
909 | struct jpeg_compress_struct cinfo; | ||
910 | unsigned char *buf; | ||
911 | |||
912 | buf = alloca(3 * w); | ||
913 | |||
914 | cinfo.err = jpeg_std_error(&(jerr.pub)); | ||
915 | jerr.pub.error_exit = _JPEGFatalErrorHandler; | ||
916 | jerr.pub.emit_message = _JPEGErrorHandler2; | ||
917 | jerr.pub.output_message = _JPEGErrorHandler; | ||
918 | if (setjmp(jerr.setjmp_buffer)) | ||
919 | return NULL; | ||
920 | |||
921 | jpeg_create_compress(&cinfo); | ||
922 | if (eet_jpeg_membuf_dst(&cinfo, &dst, &sz)) | ||
923 | { | ||
924 | jpeg_destroy_compress(&cinfo); | ||
925 | return NULL; | ||
926 | } | ||
927 | |||
928 | cinfo.image_width = w; | ||
929 | cinfo.image_height = h; | ||
930 | cinfo.input_components = 3; | ||
931 | cinfo.in_color_space = JCS_RGB; | ||
932 | cinfo.optimize_coding = FALSE; | ||
933 | cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss) | ||
934 | if (quality < 60) cinfo.dct_method = JDCT_IFAST; | ||
935 | jpeg_set_defaults(&cinfo); | ||
936 | jpeg_set_quality(&cinfo, quality, TRUE); | ||
937 | if (quality >= 90) | ||
938 | { | ||
939 | cinfo.comp_info[0].h_samp_factor = 1; | ||
940 | cinfo.comp_info[0].v_samp_factor = 1; | ||
941 | cinfo.comp_info[1].h_samp_factor = 1; | ||
942 | cinfo.comp_info[1].v_samp_factor = 1; | ||
943 | cinfo.comp_info[2].h_samp_factor = 1; | ||
944 | cinfo.comp_info[2].v_samp_factor = 1; | ||
945 | } | ||
946 | |||
947 | jpeg_start_compress(&cinfo, TRUE); | ||
948 | |||
949 | while (cinfo.next_scanline < cinfo.image_height) | ||
950 | { | ||
951 | unsigned int i, j; | ||
952 | |||
953 | ptr = ((const int *)data) + cinfo.next_scanline * w; | ||
954 | /* convert scaline from ARGB to RGB packed */ | ||
955 | for (j = 0, i = 0; i < w; i++) | ||
956 | { | ||
957 | buf[j++] = ((*ptr) >> 16) & 0xff; | ||
958 | buf[j++] = ((*ptr) >> 8) & 0xff; | ||
959 | buf[j++] = ((*ptr)) & 0xff; | ||
960 | ptr++; | ||
961 | } | ||
962 | jbuf = (JSAMPROW *)(&buf); | ||
963 | jpeg_write_scanlines(&cinfo, jbuf, 1); | ||
964 | } | ||
965 | |||
966 | jpeg_finish_compress(&cinfo); | ||
967 | jpeg_destroy_compress(&cinfo); | ||
968 | |||
969 | d1 = dst; | ||
970 | sz1 = sz; | ||
971 | } | ||
972 | { | ||
973 | const int *ptr; | ||
974 | void *dst = NULL; | ||
975 | size_t sz = 0; | ||
976 | struct _JPEG_error_mgr jerr; | ||
977 | JSAMPROW *jbuf; | ||
978 | struct jpeg_compress_struct cinfo; | ||
979 | unsigned char *buf; | ||
980 | |||
981 | buf = alloca(3 * w); | ||
982 | |||
983 | cinfo.err = jpeg_std_error(&(jerr.pub)); | ||
984 | jerr.pub.error_exit = _JPEGFatalErrorHandler; | ||
985 | jerr.pub.emit_message = _JPEGErrorHandler2; | ||
986 | jerr.pub.output_message = _JPEGErrorHandler; | ||
987 | if (setjmp(jerr.setjmp_buffer)) | ||
988 | { | ||
989 | free(d1); | ||
990 | return NULL; | ||
991 | } | ||
992 | |||
993 | jpeg_create_compress(&cinfo); | ||
994 | if (eet_jpeg_membuf_dst(&cinfo, &dst, &sz)) | ||
995 | { | ||
996 | jpeg_destroy_compress(&cinfo); | ||
997 | free(d1); | ||
998 | return NULL; | ||
999 | } | ||
1000 | |||
1001 | cinfo.image_width = w; | ||
1002 | cinfo.image_height = h; | ||
1003 | cinfo.input_components = 1; | ||
1004 | cinfo.in_color_space = JCS_GRAYSCALE; | ||
1005 | jpeg_set_defaults(&cinfo); | ||
1006 | jpeg_set_quality(&cinfo, quality, TRUE); | ||
1007 | if (quality >= 90) | ||
1008 | { | ||
1009 | cinfo.comp_info[0].h_samp_factor = 1; | ||
1010 | cinfo.comp_info[0].v_samp_factor = 1; | ||
1011 | cinfo.comp_info[1].h_samp_factor = 1; | ||
1012 | cinfo.comp_info[1].v_samp_factor = 1; | ||
1013 | cinfo.comp_info[2].h_samp_factor = 1; | ||
1014 | cinfo.comp_info[2].v_samp_factor = 1; | ||
1015 | } | ||
1016 | |||
1017 | jpeg_start_compress(&cinfo, TRUE); | ||
1018 | |||
1019 | while (cinfo.next_scanline < cinfo.image_height) | ||
1020 | { | ||
1021 | unsigned int i, j; | ||
1022 | |||
1023 | ptr = ((const int *)data) + cinfo.next_scanline * w; | ||
1024 | /* convert scaline from ARGB to RGB packed */ | ||
1025 | for (j = 0, i = 0; i < w; i++) | ||
1026 | { | ||
1027 | buf[j++] = ((*ptr) >> 24) & 0xff; | ||
1028 | ptr++; | ||
1029 | } | ||
1030 | jbuf = (JSAMPROW *)(&buf); | ||
1031 | jpeg_write_scanlines(&cinfo, jbuf, 1); | ||
1032 | } | ||
1033 | |||
1034 | jpeg_finish_compress(&cinfo); | ||
1035 | jpeg_destroy_compress(&cinfo); | ||
1036 | |||
1037 | d2 = dst; | ||
1038 | sz2 = sz; | ||
1039 | } | ||
1040 | d = malloc(12 + sz1 + sz2); | ||
1041 | if (!d) | ||
1042 | { | ||
1043 | free(d1); | ||
1044 | free(d2); | ||
1045 | return NULL; | ||
1046 | } | ||
1047 | |||
1048 | header = (int *)d; | ||
1049 | header[0] = 0xbeeff00d; | ||
1050 | header[1] = sz1; | ||
1051 | header[2] = sz2; | ||
1052 | if (_eet_image_words_bigendian) | ||
1053 | { | ||
1054 | int i; | ||
1055 | |||
1056 | for (i = 0; i < 3; i++) SWAP32(header[i]); | ||
1057 | } | ||
1058 | |||
1059 | memcpy(d + 12, d1, sz1); | ||
1060 | memcpy(d + 12 + sz1, d2, sz2); | ||
1061 | |||
1062 | free(d1); | ||
1063 | free(d2); | ||
1064 | *size = 12 + sz1 + sz2; | ||
1065 | return d; | ||
1066 | } /* eet_data_image_jpeg_alpha_convert */ | ||
1067 | |||
1068 | EAPI int | ||
1069 | eet_data_image_write_cipher(Eet_File *ef, | ||
1070 | const char *name, | ||
1071 | const char *cipher_key, | ||
1072 | const void *data, | ||
1073 | unsigned int w, | ||
1074 | unsigned int h, | ||
1075 | int alpha, | ||
1076 | int comp, | ||
1077 | int quality, | ||
1078 | int lossy) | ||
1079 | { | ||
1080 | void *d = NULL; | ||
1081 | int size = 0; | ||
1082 | |||
1083 | d = eet_data_image_encode(data, &size, w, h, alpha, comp, quality, lossy); | ||
1084 | if (d) | ||
1085 | { | ||
1086 | int v; | ||
1087 | |||
1088 | v = eet_write_cipher(ef, name, d, size, 0, cipher_key); | ||
1089 | free(d); | ||
1090 | return v; | ||
1091 | } | ||
1092 | |||
1093 | return 0; | ||
1094 | } /* eet_data_image_write_cipher */ | ||
1095 | |||
1096 | EAPI int | ||
1097 | eet_data_image_write(Eet_File *ef, | ||
1098 | const char *name, | ||
1099 | const void *data, | ||
1100 | unsigned int w, | ||
1101 | unsigned int h, | ||
1102 | int alpha, | ||
1103 | int comp, | ||
1104 | int quality, | ||
1105 | int lossy) | ||
1106 | { | ||
1107 | return eet_data_image_write_cipher(ef, | ||
1108 | name, | ||
1109 | NULL, | ||
1110 | data, | ||
1111 | w, | ||
1112 | h, | ||
1113 | alpha, | ||
1114 | comp, | ||
1115 | quality, | ||
1116 | lossy); | ||
1117 | } /* eet_data_image_write */ | ||
1118 | |||
1119 | EAPI void * | ||
1120 | eet_data_image_read_cipher(Eet_File *ef, | ||
1121 | const char *name, | ||
1122 | const char *cipher_key, | ||
1123 | unsigned int *w, | ||
1124 | unsigned int *h, | ||
1125 | int *alpha, | ||
1126 | int *comp, | ||
1127 | int *quality, | ||
1128 | int *lossy) | ||
1129 | { | ||
1130 | unsigned int *d = NULL; | ||
1131 | void *data = NULL; | ||
1132 | int free_data = 0; | ||
1133 | int size; | ||
1134 | |||
1135 | if (!cipher_key) | ||
1136 | data = (void *)eet_read_direct(ef, name, &size); | ||
1137 | |||
1138 | if (!data) | ||
1139 | { | ||
1140 | data = eet_read_cipher(ef, name, &size, cipher_key); | ||
1141 | free_data = 1; | ||
1142 | if (!data) | ||
1143 | return NULL; | ||
1144 | } | ||
1145 | |||
1146 | d = eet_data_image_decode(data, size, w, h, alpha, comp, quality, lossy); | ||
1147 | |||
1148 | if (free_data) | ||
1149 | free(data); | ||
1150 | |||
1151 | return d; | ||
1152 | } /* eet_data_image_read_cipher */ | ||
1153 | |||
1154 | EAPI void * | ||
1155 | eet_data_image_read(Eet_File *ef, | ||
1156 | const char *name, | ||
1157 | unsigned int *w, | ||
1158 | unsigned int *h, | ||
1159 | int *alpha, | ||
1160 | int *comp, | ||
1161 | int *quality, | ||
1162 | int *lossy) | ||
1163 | { | ||
1164 | return eet_data_image_read_cipher(ef, name, NULL, w, h, alpha, | ||
1165 | comp, quality, lossy); | ||
1166 | } /* eet_data_image_read */ | ||
1167 | |||
1168 | EAPI int | ||
1169 | eet_data_image_read_to_surface_cipher(Eet_File *ef, | ||
1170 | const char *name, | ||
1171 | const char *cipher_key, | ||
1172 | unsigned int src_x, | ||
1173 | unsigned int src_y, | ||
1174 | unsigned int *d, | ||
1175 | unsigned int w, | ||
1176 | unsigned int h, | ||
1177 | unsigned int row_stride, | ||
1178 | int *alpha, | ||
1179 | int *comp, | ||
1180 | int *quality, | ||
1181 | int *lossy) | ||
1182 | { | ||
1183 | void *data = NULL; | ||
1184 | int free_data = 0; | ||
1185 | int res = 1; | ||
1186 | int size; | ||
1187 | |||
1188 | if (!cipher_key) | ||
1189 | data = (void *)eet_read_direct(ef, name, &size); | ||
1190 | |||
1191 | if (!data) | ||
1192 | { | ||
1193 | data = eet_read_cipher(ef, name, &size, cipher_key); | ||
1194 | free_data = 1; | ||
1195 | if (!data) | ||
1196 | return 0; | ||
1197 | } | ||
1198 | |||
1199 | res = eet_data_image_decode_to_surface(data, size, src_x, src_y, d, | ||
1200 | w, h, row_stride, alpha, | ||
1201 | comp, quality, lossy); | ||
1202 | |||
1203 | if (free_data) | ||
1204 | free(data); | ||
1205 | |||
1206 | return res; | ||
1207 | } /* eet_data_image_read_to_surface_cipher */ | ||
1208 | |||
1209 | EAPI int | ||
1210 | eet_data_image_read_to_surface(Eet_File *ef, | ||
1211 | const char *name, | ||
1212 | unsigned int src_x, | ||
1213 | unsigned int src_y, | ||
1214 | unsigned int *d, | ||
1215 | unsigned int w, | ||
1216 | unsigned int h, | ||
1217 | unsigned int row_stride, | ||
1218 | int *alpha, | ||
1219 | int *comp, | ||
1220 | int *quality, | ||
1221 | int *lossy) | ||
1222 | { | ||
1223 | return eet_data_image_read_to_surface_cipher(ef, name, NULL, | ||
1224 | src_x, src_y, d, | ||
1225 | w, h, row_stride, | ||
1226 | alpha, comp, quality, | ||
1227 | lossy); | ||
1228 | } /* eet_data_image_read_to_surface */ | ||
1229 | |||
1230 | EAPI int | ||
1231 | eet_data_image_header_read_cipher(Eet_File *ef, | ||
1232 | const char *name, | ||
1233 | const char *cipher_key, | ||
1234 | unsigned int *w, | ||
1235 | unsigned int *h, | ||
1236 | int *alpha, | ||
1237 | int *comp, | ||
1238 | int *quality, | ||
1239 | int *lossy) | ||
1240 | { | ||
1241 | void *data = NULL; | ||
1242 | int size = 0; | ||
1243 | int free_data = 0; | ||
1244 | int d; | ||
1245 | |||
1246 | if (!cipher_key) | ||
1247 | data = (void *)eet_read_direct(ef, name, &size); | ||
1248 | |||
1249 | if (!data) | ||
1250 | { | ||
1251 | data = eet_read_cipher(ef, name, &size, cipher_key); | ||
1252 | free_data = 1; | ||
1253 | if (!data) | ||
1254 | return 0; | ||
1255 | } | ||
1256 | |||
1257 | d = eet_data_image_header_decode(data, size, w, h, alpha, | ||
1258 | comp, quality, lossy); | ||
1259 | if (free_data) | ||
1260 | free(data); | ||
1261 | |||
1262 | return d; | ||
1263 | } /* eet_data_image_header_read_cipher */ | ||
1264 | |||
1265 | EAPI int | ||
1266 | eet_data_image_header_read(Eet_File *ef, | ||
1267 | const char *name, | ||
1268 | unsigned int *w, | ||
1269 | unsigned int *h, | ||
1270 | int *alpha, | ||
1271 | int *comp, | ||
1272 | int *quality, | ||
1273 | int *lossy) | ||
1274 | { | ||
1275 | return eet_data_image_header_read_cipher(ef, name, NULL, | ||
1276 | w, h, alpha, | ||
1277 | comp, quality, lossy); | ||
1278 | } /* eet_data_image_header_read */ | ||
1279 | |||
1280 | EAPI void * | ||
1281 | eet_data_image_encode_cipher(const void *data, | ||
1282 | const char *cipher_key, | ||
1283 | unsigned int w, | ||
1284 | unsigned int h, | ||
1285 | int alpha, | ||
1286 | int comp, | ||
1287 | int quality, | ||
1288 | int lossy, | ||
1289 | int *size_ret) | ||
1290 | { | ||
1291 | void *d = NULL; | ||
1292 | void *ciphered_d = NULL; | ||
1293 | unsigned int ciphered_sz = 0; | ||
1294 | int size = 0; | ||
1295 | |||
1296 | if (lossy == 0) | ||
1297 | { | ||
1298 | if (comp > 0) | ||
1299 | d = eet_data_image_lossless_compressed_convert(&size, data, | ||
1300 | w, h, alpha, comp); | ||
1301 | |||
1302 | /* eet_data_image_lossless_compressed_convert will refuse to compress something | ||
1303 | if the result is bigger than the entry. */ | ||
1304 | if (comp <= 0 || !d) | ||
1305 | d = eet_data_image_lossless_convert(&size, data, w, h, alpha); | ||
1306 | } | ||
1307 | else | ||
1308 | { | ||
1309 | if (!alpha) | ||
1310 | d = eet_data_image_jpeg_convert(&size, data, w, h, alpha, quality); | ||
1311 | else | ||
1312 | d = eet_data_image_jpeg_alpha_convert(&size, data, | ||
1313 | w, h, alpha, quality); | ||
1314 | } | ||
1315 | |||
1316 | if (cipher_key) | ||
1317 | { | ||
1318 | if(!eet_cipher(d, size, cipher_key, strlen(cipher_key), &ciphered_d, | ||
1319 | &ciphered_sz)) | ||
1320 | { | ||
1321 | if (d) | ||
1322 | free(d); | ||
1323 | |||
1324 | d = ciphered_d; | ||
1325 | size = ciphered_sz; | ||
1326 | } | ||
1327 | else | ||
1328 | if (ciphered_d) | ||
1329 | free(ciphered_d); | ||
1330 | } | ||
1331 | |||
1332 | if (size_ret) | ||
1333 | *size_ret = size; | ||
1334 | |||
1335 | return d; | ||
1336 | } /* eet_data_image_encode_cipher */ | ||
1337 | |||
1338 | EAPI void * | ||
1339 | eet_data_image_encode(const void *data, | ||
1340 | int *size_ret, | ||
1341 | unsigned int w, | ||
1342 | unsigned int h, | ||
1343 | int alpha, | ||
1344 | int comp, | ||
1345 | int quality, | ||
1346 | int lossy) | ||
1347 | { | ||
1348 | return eet_data_image_encode_cipher(data, NULL, w, h, alpha, | ||
1349 | comp, quality, lossy, size_ret); | ||
1350 | } /* eet_data_image_encode */ | ||
1351 | |||
1352 | EAPI int | ||
1353 | eet_data_image_header_decode_cipher(const void *data, | ||
1354 | const char *cipher_key, | ||
1355 | int size, | ||
1356 | unsigned int *w, | ||
1357 | unsigned int *h, | ||
1358 | int *alpha, | ||
1359 | int *comp, | ||
1360 | int *quality, | ||
1361 | int *lossy) | ||
1362 | { | ||
1363 | int header[8]; | ||
1364 | void *deciphered_d = NULL; | ||
1365 | unsigned int deciphered_sz = 0; | ||
1366 | |||
1367 | if (cipher_key) | ||
1368 | { | ||
1369 | if (!eet_decipher(data, size, cipher_key, strlen(cipher_key), | ||
1370 | &deciphered_d, &deciphered_sz)) | ||
1371 | { | ||
1372 | data = deciphered_d; | ||
1373 | size = deciphered_sz; | ||
1374 | } | ||
1375 | else | ||
1376 | if (deciphered_d) | ||
1377 | free(deciphered_d); | ||
1378 | } | ||
1379 | |||
1380 | if (_eet_image_words_bigendian == -1) | ||
1381 | { | ||
1382 | unsigned long int v; | ||
1383 | |||
1384 | v = htonl(0x12345678); | ||
1385 | if (v == 0x12345678) | ||
1386 | _eet_image_words_bigendian = 1; | ||
1387 | else | ||
1388 | _eet_image_words_bigendian = 0; | ||
1389 | } | ||
1390 | |||
1391 | if (size < 32) | ||
1392 | return 0; | ||
1393 | |||
1394 | memcpy(header, data, 32); | ||
1395 | if (_eet_image_words_bigendian) | ||
1396 | { | ||
1397 | int i; | ||
1398 | |||
1399 | for (i = 0; i < 8; i++) SWAP32(header[i]); | ||
1400 | } | ||
1401 | |||
1402 | if ((unsigned)header[0] == 0xac1dfeed) | ||
1403 | { | ||
1404 | int iw, ih, al, cp; | ||
1405 | |||
1406 | iw = header[1]; | ||
1407 | ih = header[2]; | ||
1408 | al = header[3]; | ||
1409 | cp = header[4]; | ||
1410 | if ((iw < 1) || (ih < 1) || (iw > 8192) || (ih > 8192)) | ||
1411 | return 0; | ||
1412 | |||
1413 | if ((cp == 0) && (size < ((iw * ih * 4) + 32))) | ||
1414 | return 0; | ||
1415 | |||
1416 | if (w) | ||
1417 | *w = iw; | ||
1418 | |||
1419 | if (h) | ||
1420 | *h = ih; | ||
1421 | |||
1422 | if (alpha) | ||
1423 | *alpha = al ? 1 : 0; | ||
1424 | |||
1425 | if (comp) | ||
1426 | *comp = cp; | ||
1427 | |||
1428 | if (lossy) | ||
1429 | *lossy = 0; | ||
1430 | |||
1431 | if (quality) | ||
1432 | *quality = 100; | ||
1433 | |||
1434 | return 1; | ||
1435 | } | ||
1436 | else if ((unsigned)header[0] == 0xbeeff00d) | ||
1437 | { | ||
1438 | unsigned int iw = 0, ih = 0; | ||
1439 | unsigned const char *dt; | ||
1440 | int sz1; | ||
1441 | int ok; | ||
1442 | |||
1443 | sz1 = header[1]; | ||
1444 | /* sz2 = header[2]; */ | ||
1445 | dt = data; | ||
1446 | dt += 12; | ||
1447 | ok = eet_data_image_jpeg_header_decode(dt, sz1, &iw, &ih); | ||
1448 | if (ok) | ||
1449 | { | ||
1450 | if (w) | ||
1451 | *w = iw; | ||
1452 | |||
1453 | if (h) | ||
1454 | *h = ih; | ||
1455 | |||
1456 | if (alpha) | ||
1457 | *alpha = 1; | ||
1458 | |||
1459 | if (comp) | ||
1460 | *comp = 0; | ||
1461 | |||
1462 | if (lossy) | ||
1463 | *lossy = 1; | ||
1464 | |||
1465 | if (quality) | ||
1466 | *quality = 75; | ||
1467 | |||
1468 | return 1; | ||
1469 | } | ||
1470 | } | ||
1471 | else | ||
1472 | { | ||
1473 | unsigned int iw = 0, ih = 0; | ||
1474 | int ok; | ||
1475 | |||
1476 | ok = eet_data_image_jpeg_header_decode(data, size, &iw, &ih); | ||
1477 | if (ok) | ||
1478 | { | ||
1479 | if (w) | ||
1480 | *w = iw; | ||
1481 | |||
1482 | if (h) | ||
1483 | *h = ih; | ||
1484 | |||
1485 | if (alpha) | ||
1486 | *alpha = 0; | ||
1487 | |||
1488 | if (comp) | ||
1489 | *comp = 0; | ||
1490 | |||
1491 | if (lossy) | ||
1492 | *lossy = 1; | ||
1493 | |||
1494 | if (quality) | ||
1495 | *quality = 75; | ||
1496 | |||
1497 | return 1; | ||
1498 | } | ||
1499 | } | ||
1500 | |||
1501 | return 0; | ||
1502 | } /* eet_data_image_header_decode_cipher */ | ||
1503 | |||
1504 | EAPI int | ||
1505 | eet_data_image_header_decode(const void *data, | ||
1506 | int size, | ||
1507 | unsigned int *w, | ||
1508 | unsigned int *h, | ||
1509 | int *alpha, | ||
1510 | int *comp, | ||
1511 | int *quality, | ||
1512 | int *lossy) | ||
1513 | { | ||
1514 | return eet_data_image_header_decode_cipher(data, | ||
1515 | NULL, | ||
1516 | size, | ||
1517 | w, | ||
1518 | h, | ||
1519 | alpha, | ||
1520 | comp, | ||
1521 | quality, | ||
1522 | lossy); | ||
1523 | } /* eet_data_image_header_decode */ | ||
1524 | |||
1525 | static void | ||
1526 | _eet_data_image_copy_buffer(const unsigned int *src, | ||
1527 | unsigned int src_x, | ||
1528 | unsigned int src_y, | ||
1529 | unsigned int src_w, | ||
1530 | unsigned int *dst, | ||
1531 | unsigned int w, | ||
1532 | unsigned int h, | ||
1533 | unsigned int row_stride) | ||
1534 | { | ||
1535 | src += src_x + src_y * src_w; | ||
1536 | |||
1537 | if (row_stride == src_w * 4 && w == src_w) | ||
1538 | memcpy(dst, src, row_stride * h); | ||
1539 | else | ||
1540 | { | ||
1541 | unsigned int *over = dst; | ||
1542 | unsigned int y; | ||
1543 | |||
1544 | for (y = 0; y < h; ++y, src += src_w, over += row_stride) | ||
1545 | memcpy(over, src, w * 4); | ||
1546 | } | ||
1547 | } /* _eet_data_image_copy_buffer */ | ||
1548 | |||
1549 | static int | ||
1550 | _eet_data_image_decode_inside(const void *data, | ||
1551 | int size, | ||
1552 | unsigned int src_x, | ||
1553 | unsigned int src_y, | ||
1554 | unsigned int src_w, | ||
1555 | unsigned int src_h, | ||
1556 | unsigned int *d, | ||
1557 | unsigned int w, | ||
1558 | unsigned int h, | ||
1559 | unsigned int row_stride, | ||
1560 | int alpha, | ||
1561 | int comp, | ||
1562 | int quality, | ||
1563 | int lossy) | ||
1564 | { | ||
1565 | if (lossy == 0 && quality == 100) | ||
1566 | { | ||
1567 | unsigned int *body; | ||
1568 | |||
1569 | body = ((unsigned int *)data) + 8; | ||
1570 | if (!comp) | ||
1571 | _eet_data_image_copy_buffer(body, src_x, src_y, src_w, d, | ||
1572 | w, h, row_stride); | ||
1573 | else | ||
1574 | { | ||
1575 | if (src_h == h && src_w == w && row_stride == src_w * 4) | ||
1576 | { | ||
1577 | uLongf dlen; | ||
1578 | |||
1579 | dlen = w * h * 4; | ||
1580 | uncompress((Bytef *)d, &dlen, (Bytef *)body, | ||
1581 | (uLongf)(size - 32)); | ||
1582 | } | ||
1583 | else | ||
1584 | { | ||
1585 | Bytef *dtmp; | ||
1586 | uLongf dlen = src_w * src_h * 4; | ||
1587 | |||
1588 | /* FIXME: This could create a huge alloc. So compressed | ||
1589 | data and tile could not always work. */ | ||
1590 | dtmp = malloc(dlen); | ||
1591 | if (!dtmp) | ||
1592 | return 0; | ||
1593 | |||
1594 | uncompress(dtmp, &dlen, (Bytef *)body, (uLongf)(size - 32)); | ||
1595 | |||
1596 | _eet_data_image_copy_buffer((unsigned int *)dtmp, | ||
1597 | src_x, src_y, src_w, d, | ||
1598 | w, h, row_stride); | ||
1599 | |||
1600 | free(dtmp); | ||
1601 | } | ||
1602 | } | ||
1603 | |||
1604 | /* Fix swapiness. */ | ||
1605 | if (_eet_image_words_bigendian) | ||
1606 | { | ||
1607 | unsigned int x; | ||
1608 | |||
1609 | for (x = 0; x < (w * h); x++) SWAP32(d[x]); | ||
1610 | } | ||
1611 | } | ||
1612 | else if (comp == 0 && lossy == 1) | ||
1613 | { | ||
1614 | if (alpha) | ||
1615 | { | ||
1616 | unsigned const char *dt; | ||
1617 | int header[8]; | ||
1618 | int sz1, sz2; | ||
1619 | |||
1620 | memcpy(header, data, 32); | ||
1621 | if (_eet_image_words_bigendian) | ||
1622 | { | ||
1623 | int i; | ||
1624 | |||
1625 | for (i = 0; i < 8; i++) SWAP32(header[i]); | ||
1626 | } | ||
1627 | |||
1628 | sz1 = header[1]; | ||
1629 | sz2 = header[2]; | ||
1630 | dt = data; | ||
1631 | dt += 12; | ||
1632 | |||
1633 | if (eet_data_image_jpeg_rgb_decode(dt, sz1, src_x, src_y, d, w, h, | ||
1634 | row_stride)) | ||
1635 | { | ||
1636 | dt += sz1; | ||
1637 | if (!eet_data_image_jpeg_alpha_decode(dt, sz2, src_x, src_y, | ||
1638 | d, w, h, row_stride)) | ||
1639 | return 0; | ||
1640 | } | ||
1641 | } | ||
1642 | else if (!eet_data_image_jpeg_rgb_decode(data, size, src_x, src_y, d, w, | ||
1643 | h, row_stride)) | ||
1644 | return 0; | ||
1645 | } | ||
1646 | else | ||
1647 | abort(); | ||
1648 | |||
1649 | return 1; | ||
1650 | } /* _eet_data_image_decode_inside */ | ||
1651 | |||
1652 | EAPI void * | ||
1653 | eet_data_image_decode_cipher(const void *data, | ||
1654 | const char *cipher_key, | ||
1655 | int size, | ||
1656 | unsigned int *w, | ||
1657 | unsigned int *h, | ||
1658 | int *alpha, | ||
1659 | int *comp, | ||
1660 | int *quality, | ||
1661 | int *lossy) | ||
1662 | { | ||
1663 | unsigned int *d = NULL; | ||
1664 | unsigned int iw, ih; | ||
1665 | int ialpha, icompress, iquality, ilossy; | ||
1666 | void *deciphered_d = NULL; | ||
1667 | unsigned int deciphered_sz = 0; | ||
1668 | |||
1669 | if (cipher_key) | ||
1670 | { | ||
1671 | if (!eet_decipher(data, size, cipher_key, strlen(cipher_key), | ||
1672 | &deciphered_d, &deciphered_sz)) | ||
1673 | { | ||
1674 | data = deciphered_d; | ||
1675 | size = deciphered_sz; | ||
1676 | } | ||
1677 | else | ||
1678 | if (deciphered_d) | ||
1679 | free(deciphered_d); | ||
1680 | } | ||
1681 | |||
1682 | /* All check are done during header decode, this simplify the code a lot. */ | ||
1683 | if (!eet_data_image_header_decode(data, size, &iw, &ih, &ialpha, &icompress, | ||
1684 | &iquality, &ilossy)) | ||
1685 | return NULL; | ||
1686 | |||
1687 | d = malloc(iw * ih * 4); | ||
1688 | if (!d) | ||
1689 | return NULL; | ||
1690 | |||
1691 | if (!_eet_data_image_decode_inside(data, size, 0, 0, iw, ih, d, iw, ih, iw * | ||
1692 | 4, ialpha, icompress, iquality, ilossy)) | ||
1693 | { | ||
1694 | free(d); | ||
1695 | return NULL; | ||
1696 | } | ||
1697 | |||
1698 | if (w) | ||
1699 | *w = iw; | ||
1700 | |||
1701 | if (h) | ||
1702 | *h = ih; | ||
1703 | |||
1704 | if (alpha) | ||
1705 | *alpha = ialpha; | ||
1706 | |||
1707 | if (comp) | ||
1708 | *comp = icompress; | ||
1709 | |||
1710 | if (quality) | ||
1711 | *quality = iquality; | ||
1712 | |||
1713 | if (lossy) | ||
1714 | *lossy = ilossy; | ||
1715 | |||
1716 | return d; | ||
1717 | } /* eet_data_image_decode_cipher */ | ||
1718 | |||
1719 | EAPI void * | ||
1720 | eet_data_image_decode(const void *data, | ||
1721 | int size, | ||
1722 | unsigned int *w, | ||
1723 | unsigned int *h, | ||
1724 | int *alpha, | ||
1725 | int *comp, | ||
1726 | int *quality, | ||
1727 | int *lossy) | ||
1728 | { | ||
1729 | return eet_data_image_decode_cipher(data, NULL, size, w, h, | ||
1730 | alpha, comp, quality, lossy); | ||
1731 | } /* eet_data_image_decode */ | ||
1732 | |||
1733 | EAPI int | ||
1734 | eet_data_image_decode_to_surface_cipher(const void *data, | ||
1735 | const char *cipher_key, | ||
1736 | int size, | ||
1737 | unsigned int src_x, | ||
1738 | unsigned int src_y, | ||
1739 | unsigned int *d, | ||
1740 | unsigned int w, | ||
1741 | unsigned int h, | ||
1742 | unsigned int row_stride, | ||
1743 | int *alpha, | ||
1744 | int *comp, | ||
1745 | int *quality, | ||
1746 | int *lossy) | ||
1747 | { | ||
1748 | unsigned int iw, ih; | ||
1749 | int ialpha, icompress, iquality, ilossy; | ||
1750 | void *deciphered_d = NULL; | ||
1751 | unsigned int deciphered_sz = 0; | ||
1752 | |||
1753 | if (cipher_key) | ||
1754 | { | ||
1755 | if (!eet_decipher(data, size, cipher_key, strlen(cipher_key), | ||
1756 | &deciphered_d, &deciphered_sz)) | ||
1757 | { | ||
1758 | data = deciphered_d; | ||
1759 | size = deciphered_sz; | ||
1760 | } | ||
1761 | else | ||
1762 | if (deciphered_d) | ||
1763 | free(deciphered_d); | ||
1764 | } | ||
1765 | |||
1766 | /* All check are done during header decode, this simplify the code a lot. */ | ||
1767 | if (!eet_data_image_header_decode(data, size, &iw, &ih, &ialpha, &icompress, | ||
1768 | &iquality, &ilossy)) | ||
1769 | return 0; | ||
1770 | |||
1771 | if (!d) | ||
1772 | return 0; | ||
1773 | |||
1774 | if (w * 4 > row_stride) | ||
1775 | return 0; | ||
1776 | |||
1777 | if (w > iw || h > ih) | ||
1778 | return 0; | ||
1779 | |||
1780 | if (!_eet_data_image_decode_inside(data, size, src_x, src_y, iw, ih, d, w, h, | ||
1781 | row_stride, ialpha, icompress, iquality, | ||
1782 | ilossy)) | ||
1783 | return 0; | ||
1784 | |||
1785 | if (alpha) | ||
1786 | *alpha = ialpha; | ||
1787 | |||
1788 | if (comp) | ||
1789 | *comp = icompress; | ||
1790 | |||
1791 | if (quality) | ||
1792 | *quality = iquality; | ||
1793 | |||
1794 | if (lossy) | ||
1795 | *lossy = ilossy; | ||
1796 | |||
1797 | return 1; | ||
1798 | } /* eet_data_image_decode_to_surface_cipher */ | ||
1799 | |||
1800 | EAPI int | ||
1801 | eet_data_image_decode_to_surface(const void *data, | ||
1802 | int size, | ||
1803 | unsigned int src_x, | ||
1804 | unsigned int src_y, | ||
1805 | unsigned int *d, | ||
1806 | unsigned int w, | ||
1807 | unsigned int h, | ||
1808 | unsigned int row_stride, | ||
1809 | int *alpha, | ||
1810 | int *comp, | ||
1811 | int *quality, | ||
1812 | int *lossy) | ||
1813 | { | ||
1814 | return eet_data_image_decode_to_surface_cipher(data, NULL, size, | ||
1815 | src_x, src_y, d, | ||
1816 | w, h, row_stride, | ||
1817 | alpha, comp, quality, | ||
1818 | lossy); | ||
1819 | } /* eet_data_image_decode_to_surface */ | ||
1820 | |||
diff --git a/libraries/eet/src/lib/eet_lib.c b/libraries/eet/src/lib/eet_lib.c new file mode 100644 index 0000000..a0d6435 --- /dev/null +++ b/libraries/eet/src/lib/eet_lib.c | |||
@@ -0,0 +1,2648 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif /* ifdef HAVE_CONFIG_H */ | ||
4 | |||
5 | #ifdef HAVE_ALLOCA_H | ||
6 | # include <alloca.h> | ||
7 | #elif defined __GNUC__ | ||
8 | # define alloca __builtin_alloca | ||
9 | #elif defined _AIX | ||
10 | # define alloca __alloca | ||
11 | #elif defined _MSC_VER | ||
12 | # include <malloc.h> | ||
13 | # define alloca _alloca | ||
14 | #else /* ifdef HAVE_ALLOCA_H */ | ||
15 | # include <stddef.h> | ||
16 | # ifdef __cplusplus | ||
17 | extern "C" | ||
18 | # endif /* ifdef __cplusplus */ | ||
19 | void *alloca(size_t); | ||
20 | #endif /* ifdef HAVE_ALLOCA_H */ | ||
21 | |||
22 | #ifdef _WIN32 | ||
23 | # include <winsock2.h> | ||
24 | #endif /* ifdef _WIN32 */ | ||
25 | |||
26 | #include <stdio.h> | ||
27 | #include <errno.h> | ||
28 | #include <sys/types.h> | ||
29 | #include <sys/stat.h> | ||
30 | #include <time.h> | ||
31 | #include <string.h> | ||
32 | #include <fnmatch.h> | ||
33 | #include <fcntl.h> | ||
34 | #include <zlib.h> | ||
35 | |||
36 | #ifdef HAVE_UNISTD_H | ||
37 | # include <unistd.h> | ||
38 | #endif /* ifdef HAVE_UNISTD_H */ | ||
39 | |||
40 | #ifdef HAVE_NETINET_IN_H | ||
41 | # include <netinet/in.h> | ||
42 | #endif /* ifdef HAVE_NETINET_IN_H */ | ||
43 | |||
44 | #ifdef HAVE_EVIL | ||
45 | # include <Evil.h> | ||
46 | #endif /* ifdef HAVE_EVIL */ | ||
47 | |||
48 | #include <Eina.h> | ||
49 | |||
50 | #ifdef HAVE_GNUTLS | ||
51 | # include <gnutls/gnutls.h> | ||
52 | # include <gcrypt.h> | ||
53 | #endif /* ifdef HAVE_GNUTLS */ | ||
54 | |||
55 | #ifdef HAVE_OPENSSL | ||
56 | # include <openssl/err.h> | ||
57 | # include <openssl/evp.h> | ||
58 | #endif /* ifdef HAVE_OPENSSL */ | ||
59 | |||
60 | #ifdef EINA_HAVE_THREADS | ||
61 | # ifdef HAVE_GNUTLS | ||
62 | GCRY_THREAD_OPTION_PTHREAD_IMPL; | ||
63 | # endif /* ifdef HAVE_GNUTLS */ | ||
64 | #endif /* ifdef EINA_HAVE_THREADS */ | ||
65 | |||
66 | #include "Eet.h" | ||
67 | #include "Eet_private.h" | ||
68 | |||
69 | #ifndef O_BINARY | ||
70 | # define O_BINARY 0 | ||
71 | #endif | ||
72 | |||
73 | static Eet_Version _version = { VMAJ, VMIN, VMIC, VREV }; | ||
74 | EAPI Eet_Version *eet_version = &_version; | ||
75 | |||
76 | #ifdef HAVE_REALPATH | ||
77 | # undef HAVE_REALPATH | ||
78 | #endif /* ifdef HAVE_REALPATH */ | ||
79 | |||
80 | #define EET_MAGIC_FILE 0x1ee7ff00 | ||
81 | #define EET_MAGIC_FILE_HEADER 0x1ee7ff01 | ||
82 | |||
83 | #define EET_MAGIC_FILE2 0x1ee70f42 | ||
84 | |||
85 | typedef struct _Eet_File_Header Eet_File_Header; | ||
86 | typedef struct _Eet_File_Node Eet_File_Node; | ||
87 | typedef struct _Eet_File_Directory Eet_File_Directory; | ||
88 | |||
89 | struct _Eet_File | ||
90 | { | ||
91 | char *path; | ||
92 | Eina_File *readfp; | ||
93 | Eet_File_Header *header; | ||
94 | Eet_Dictionary *ed; | ||
95 | Eet_Key *key; | ||
96 | const unsigned char *data; | ||
97 | const void *x509_der; | ||
98 | const void *signature; | ||
99 | void *sha1; | ||
100 | |||
101 | Eet_File_Mode mode; | ||
102 | |||
103 | int magic; | ||
104 | int references; | ||
105 | |||
106 | unsigned long int data_size; | ||
107 | int x509_length; | ||
108 | unsigned int signature_length; | ||
109 | int sha1_length; | ||
110 | |||
111 | Eina_Lock file_lock; | ||
112 | |||
113 | unsigned char writes_pending : 1; | ||
114 | unsigned char delete_me_now : 1; | ||
115 | }; | ||
116 | |||
117 | struct _Eet_File_Header | ||
118 | { | ||
119 | int magic; | ||
120 | Eet_File_Directory *directory; | ||
121 | }; | ||
122 | |||
123 | struct _Eet_File_Directory | ||
124 | { | ||
125 | int size; | ||
126 | Eet_File_Node **nodes; | ||
127 | }; | ||
128 | |||
129 | struct _Eet_File_Node | ||
130 | { | ||
131 | char *name; | ||
132 | void *data; | ||
133 | Eet_File_Node *next; /* FIXME: make buckets linked lists */ | ||
134 | |||
135 | unsigned long int offset; | ||
136 | unsigned long int dictionary_offset; | ||
137 | unsigned long int name_offset; | ||
138 | |||
139 | unsigned int name_size; | ||
140 | unsigned int size; | ||
141 | unsigned int data_size; | ||
142 | |||
143 | unsigned char free_name : 1; | ||
144 | unsigned char compression : 1; | ||
145 | unsigned char ciphered : 1; | ||
146 | unsigned char alias : 1; | ||
147 | }; | ||
148 | |||
149 | #if 0 | ||
150 | /* Version 2 */ | ||
151 | /* NB: all int's are stored in network byte order on disk */ | ||
152 | /* file format: */ | ||
153 | int magic; /* magic number ie 0x1ee7ff00 */ | ||
154 | int num_directory_entries; /* number of directory entries to follow */ | ||
155 | int bytes_directory_entries; /* bytes of directory entries to follow */ | ||
156 | struct | ||
157 | { | ||
158 | int offset; /* bytes offset into file for data chunk */ | ||
159 | int flags; /* flags - for now 0 = uncompressed and clear, 1 = compressed and clear, 2 = uncompressed and ciphered, 3 = compressed and ciphered */ | ||
160 | int size; /* size of the data chunk */ | ||
161 | int data_size; /* size of the (uncompressed) data chunk */ | ||
162 | int name_size; /* length in bytes of the name field */ | ||
163 | char name[name_size]; /* name string (variable length) and \0 terminated */ | ||
164 | } directory[num_directory_entries]; | ||
165 | /* and now startes the data stream... */ | ||
166 | #endif /* if 0 */ | ||
167 | |||
168 | #if 0 | ||
169 | /* Version 3 */ | ||
170 | /* NB: all int's are stored in network byte order on disk */ | ||
171 | /* file format: */ | ||
172 | int magic; /* magic number ie 0x1ee70f42 */ | ||
173 | int num_directory_entries; /* number of directory entries to follow */ | ||
174 | int num_dictionary_entries; /* number of dictionary entries to follow */ | ||
175 | struct | ||
176 | { | ||
177 | int data_offset; /* bytes offset into file for data chunk */ | ||
178 | int size; /* size of the data chunk */ | ||
179 | int data_size; /* size of the (uncompressed) data chunk */ | ||
180 | int name_offset; /* bytes offset into file for name string */ | ||
181 | int name_size; /* length in bytes of the name field */ | ||
182 | int flags; /* bit flags - for now: | ||
183 | bit 0 => compresion on/off | ||
184 | bit 1 => ciphered on/off | ||
185 | bit 2 => alias | ||
186 | */ | ||
187 | } directory[num_directory_entries]; | ||
188 | struct | ||
189 | { | ||
190 | int hash; | ||
191 | int offset; | ||
192 | int size; | ||
193 | int prev; | ||
194 | int next; | ||
195 | } dictionary[num_dictionary_entries]; | ||
196 | /* now start the string stream. */ | ||
197 | /* and right after them the data stream. */ | ||
198 | int magic_sign; /* Optional, only if the eet file is signed. */ | ||
199 | int signature_length; /* Signature length. */ | ||
200 | int x509_length; /* Public certificate that signed the file. */ | ||
201 | char signature[signature_length]; /* The signature. */ | ||
202 | char x509[x509_length]; /* The public certificate. */ | ||
203 | #endif /* if 0 */ | ||
204 | |||
205 | #define EET_FILE2_HEADER_COUNT 3 | ||
206 | #define EET_FILE2_DIRECTORY_ENTRY_COUNT 6 | ||
207 | #define EET_FILE2_DICTIONARY_ENTRY_COUNT 5 | ||
208 | |||
209 | #define EET_FILE2_HEADER_SIZE (sizeof(int) * \ | ||
210 | EET_FILE2_HEADER_COUNT) | ||
211 | #define EET_FILE2_DIRECTORY_ENTRY_SIZE (sizeof(int) * \ | ||
212 | EET_FILE2_DIRECTORY_ENTRY_COUNT) | ||
213 | #define EET_FILE2_DICTIONARY_ENTRY_SIZE (sizeof(int) * \ | ||
214 | EET_FILE2_DICTIONARY_ENTRY_COUNT) | ||
215 | |||
216 | /* prototypes of internal calls */ | ||
217 | static Eet_File * | ||
218 | eet_cache_find(const char *path, | ||
219 | Eet_File **cache, | ||
220 | int cache_num); | ||
221 | static void | ||
222 | eet_cache_add(Eet_File *ef, | ||
223 | Eet_File ***cache, | ||
224 | int *cache_num, | ||
225 | int *cache_alloc); | ||
226 | static void | ||
227 | eet_cache_del(Eet_File *ef, | ||
228 | Eet_File ***cache, | ||
229 | int *cache_num, | ||
230 | int *cache_alloc); | ||
231 | static int | ||
232 | eet_string_match(const char *s1, | ||
233 | const char *s2); | ||
234 | #if 0 /* Unused */ | ||
235 | static Eet_Error | ||
236 | eet_flush(Eet_File *ef); | ||
237 | #endif /* if 0 */ | ||
238 | static Eet_Error | ||
239 | eet_flush2(Eet_File *ef); | ||
240 | static Eet_File_Node * | ||
241 | find_node_by_name(Eet_File *ef, | ||
242 | const char *name); | ||
243 | static int | ||
244 | read_data_from_disk(Eet_File *ef, | ||
245 | Eet_File_Node *efn, | ||
246 | void *buf, | ||
247 | int len); | ||
248 | |||
249 | static Eet_Error | ||
250 | eet_internal_close(Eet_File *ef, | ||
251 | Eina_Bool locked); | ||
252 | |||
253 | static Eina_Lock eet_cache_lock; | ||
254 | |||
255 | #define LOCK_CACHE eina_lock_take(&eet_cache_lock) | ||
256 | #define UNLOCK_CACHE eina_lock_release(&eet_cache_lock) | ||
257 | |||
258 | #define INIT_FILE(File) eina_lock_new(&File->file_lock) | ||
259 | #define LOCK_FILE(File) eina_lock_take(&File->file_lock) | ||
260 | #define UNLOCK_FILE(File) eina_lock_release(&File->file_lock) | ||
261 | #define DESTROY_FILE(File) eina_lock_free(&File->file_lock) | ||
262 | |||
263 | /* cache. i don't expect this to ever be large, so arrays will do */ | ||
264 | static int eet_writers_num = 0; | ||
265 | static int eet_writers_alloc = 0; | ||
266 | static Eet_File **eet_writers = NULL; | ||
267 | static int eet_readers_num = 0; | ||
268 | static int eet_readers_alloc = 0; | ||
269 | static Eet_File **eet_readers = NULL; | ||
270 | static int eet_init_count = 0; | ||
271 | |||
272 | /* log domain variable */ | ||
273 | int _eet_log_dom_global = -1; | ||
274 | |||
275 | /* Check to see its' an eet file pointer */ | ||
276 | static inline int | ||
277 | eet_check_pointer(const Eet_File *ef) | ||
278 | { | ||
279 | if ((!ef) || (ef->magic != EET_MAGIC_FILE)) | ||
280 | return 1; | ||
281 | |||
282 | return 0; | ||
283 | } /* eet_check_pointer */ | ||
284 | |||
285 | static inline int | ||
286 | eet_check_header(const Eet_File *ef) | ||
287 | { | ||
288 | if (!ef->header) | ||
289 | return 1; | ||
290 | |||
291 | if (!ef->header->directory) | ||
292 | return 1; | ||
293 | |||
294 | return 0; | ||
295 | } /* eet_check_header */ | ||
296 | |||
297 | static inline int | ||
298 | eet_test_close(int test, | ||
299 | Eet_File *ef) | ||
300 | { | ||
301 | if (test) | ||
302 | { | ||
303 | ef->delete_me_now = 1; | ||
304 | eet_internal_close(ef, EINA_TRUE); | ||
305 | } | ||
306 | |||
307 | return test; | ||
308 | } /* eet_test_close */ | ||
309 | |||
310 | /* find an eet file in the currently in use cache */ | ||
311 | static Eet_File * | ||
312 | eet_cache_find(const char *path, | ||
313 | Eet_File **cache, | ||
314 | int cache_num) | ||
315 | { | ||
316 | int i; | ||
317 | |||
318 | /* walk list */ | ||
319 | for (i = 0; i < cache_num; i++) | ||
320 | { | ||
321 | /* if matches real path - return it */ | ||
322 | if (eet_string_match(cache[i]->path, path)) | ||
323 | if (!cache[i]->delete_me_now) | ||
324 | return cache[i]; | ||
325 | } | ||
326 | |||
327 | /* not found */ | ||
328 | return NULL; | ||
329 | } /* eet_cache_find */ | ||
330 | |||
331 | /* add to end of cache */ | ||
332 | /* this should only be called when the cache lock is already held */ | ||
333 | static void | ||
334 | eet_cache_add(Eet_File *ef, | ||
335 | Eet_File ***cache, | ||
336 | int *cache_num, | ||
337 | int *cache_alloc) | ||
338 | { | ||
339 | Eet_File **new_cache; | ||
340 | int new_cache_num; | ||
341 | int new_cache_alloc; | ||
342 | |||
343 | new_cache_num = *cache_num; | ||
344 | if (new_cache_num >= 64) /* avoid fd overruns - limit to 128 (most recent) in the cache */ | ||
345 | { | ||
346 | Eet_File *del_ef = NULL; | ||
347 | int i; | ||
348 | |||
349 | new_cache = *cache; | ||
350 | for (i = 0; i < new_cache_num; i++) | ||
351 | { | ||
352 | if (new_cache[i]->references == 0) | ||
353 | { | ||
354 | del_ef = new_cache[i]; | ||
355 | break; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | if (del_ef) | ||
360 | { | ||
361 | del_ef->delete_me_now = 1; | ||
362 | eet_internal_close(del_ef, EINA_TRUE); | ||
363 | } | ||
364 | } | ||
365 | |||
366 | new_cache = *cache; | ||
367 | new_cache_num = *cache_num; | ||
368 | new_cache_alloc = *cache_alloc; | ||
369 | new_cache_num++; | ||
370 | if (new_cache_num > new_cache_alloc) | ||
371 | { | ||
372 | new_cache_alloc += 16; | ||
373 | new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *)); | ||
374 | if (!new_cache) | ||
375 | { | ||
376 | CRIT("BAD ERROR! Eet realloc of cache list failed. Abort"); | ||
377 | abort(); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | new_cache[new_cache_num - 1] = ef; | ||
382 | *cache = new_cache; | ||
383 | *cache_num = new_cache_num; | ||
384 | *cache_alloc = new_cache_alloc; | ||
385 | } /* eet_cache_add */ | ||
386 | |||
387 | /* delete from cache */ | ||
388 | /* this should only be called when the cache lock is already held */ | ||
389 | static void | ||
390 | eet_cache_del(Eet_File *ef, | ||
391 | Eet_File ***cache, | ||
392 | int *cache_num, | ||
393 | int *cache_alloc) | ||
394 | { | ||
395 | Eet_File **new_cache; | ||
396 | int new_cache_num, new_cache_alloc; | ||
397 | int i, j; | ||
398 | |||
399 | new_cache = *cache; | ||
400 | new_cache_num = *cache_num; | ||
401 | new_cache_alloc = *cache_alloc; | ||
402 | if (new_cache_num <= 0) | ||
403 | return; | ||
404 | |||
405 | for (i = 0; i < new_cache_num; i++) | ||
406 | { | ||
407 | if (new_cache[i] == ef) | ||
408 | break; | ||
409 | } | ||
410 | |||
411 | if (i >= new_cache_num) | ||
412 | return; | ||
413 | |||
414 | new_cache_num--; | ||
415 | for (j = i; j < new_cache_num; j++) | ||
416 | new_cache[j] = new_cache[j + 1]; | ||
417 | |||
418 | if (new_cache_num <= (new_cache_alloc - 16)) | ||
419 | { | ||
420 | new_cache_alloc -= 16; | ||
421 | if (new_cache_num > 0) | ||
422 | { | ||
423 | new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *)); | ||
424 | if (!new_cache) | ||
425 | { | ||
426 | CRIT("BAD ERROR! Eet realloc of cache list failed. Abort"); | ||
427 | abort(); | ||
428 | } | ||
429 | } | ||
430 | else | ||
431 | { | ||
432 | free(new_cache); | ||
433 | new_cache = NULL; | ||
434 | } | ||
435 | } | ||
436 | |||
437 | *cache = new_cache; | ||
438 | *cache_num = new_cache_num; | ||
439 | *cache_alloc = new_cache_alloc; | ||
440 | } /* eet_cache_del */ | ||
441 | |||
442 | /* internal string match. null friendly, catches same ptr */ | ||
443 | static int | ||
444 | eet_string_match(const char *s1, | ||
445 | const char *s2) | ||
446 | { | ||
447 | /* both null- no match */ | ||
448 | if ((!s1) || (!s2)) | ||
449 | return 0; | ||
450 | |||
451 | if (s1 == s2) | ||
452 | return 1; | ||
453 | |||
454 | return !strcmp(s1, s2); | ||
455 | } /* eet_string_match */ | ||
456 | |||
457 | /* flush out writes to a v2 eet file */ | ||
458 | static Eet_Error | ||
459 | eet_flush2(Eet_File *ef) | ||
460 | { | ||
461 | Eet_File_Node *efn; | ||
462 | FILE *fp; | ||
463 | Eet_Error error = EET_ERROR_NONE; | ||
464 | int head[EET_FILE2_HEADER_COUNT]; | ||
465 | int num_directory_entries = 0; | ||
466 | int num_dictionary_entries = 0; | ||
467 | int bytes_directory_entries = 0; | ||
468 | int bytes_dictionary_entries = 0; | ||
469 | int bytes_strings = 0; | ||
470 | int data_offset = 0; | ||
471 | int strings_offset = 0; | ||
472 | int num; | ||
473 | int i; | ||
474 | int j; | ||
475 | |||
476 | if (eet_check_pointer(ef)) | ||
477 | return EET_ERROR_BAD_OBJECT; | ||
478 | |||
479 | if (eet_check_header(ef)) | ||
480 | return EET_ERROR_EMPTY; | ||
481 | |||
482 | if (!ef->writes_pending) | ||
483 | return EET_ERROR_NONE; | ||
484 | |||
485 | if ((ef->mode == EET_FILE_MODE_READ_WRITE) | ||
486 | || (ef->mode == EET_FILE_MODE_WRITE)) | ||
487 | { | ||
488 | int fd; | ||
489 | |||
490 | /* opening for write - delete old copy of file right away */ | ||
491 | unlink(ef->path); | ||
492 | fd = open(ef->path, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, S_IRUSR | S_IWUSR); | ||
493 | fp = fdopen(fd, "wb"); | ||
494 | if (!fp) | ||
495 | return EET_ERROR_NOT_WRITABLE; | ||
496 | |||
497 | fcntl(fileno(fp), F_SETFD, FD_CLOEXEC); | ||
498 | } | ||
499 | else | ||
500 | return EET_ERROR_NOT_WRITABLE; | ||
501 | |||
502 | /* calculate string base offset and data base offset */ | ||
503 | num = (1 << ef->header->directory->size); | ||
504 | for (i = 0; i < num; ++i) | ||
505 | { | ||
506 | for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) | ||
507 | { | ||
508 | num_directory_entries++; | ||
509 | bytes_strings += strlen(efn->name) + 1; | ||
510 | } | ||
511 | } | ||
512 | if (ef->ed) | ||
513 | { | ||
514 | num_dictionary_entries = ef->ed->count; | ||
515 | |||
516 | for (i = 0; i < num_dictionary_entries; ++i) | ||
517 | bytes_strings += ef->ed->all[i].len; | ||
518 | } | ||
519 | |||
520 | /* calculate section bytes size */ | ||
521 | bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * | ||
522 | num_directory_entries + EET_FILE2_HEADER_SIZE; | ||
523 | bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * | ||
524 | num_dictionary_entries; | ||
525 | |||
526 | /* calculate per entry offset */ | ||
527 | strings_offset = bytes_directory_entries + bytes_dictionary_entries; | ||
528 | data_offset = bytes_directory_entries + bytes_dictionary_entries + | ||
529 | bytes_strings; | ||
530 | |||
531 | for (i = 0; i < num; ++i) | ||
532 | { | ||
533 | for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) | ||
534 | { | ||
535 | efn->offset = data_offset; | ||
536 | data_offset += efn->size; | ||
537 | |||
538 | efn->name_offset = strings_offset; | ||
539 | strings_offset += efn->name_size; | ||
540 | } | ||
541 | } | ||
542 | |||
543 | /* calculate dictionary strings offset */ | ||
544 | if (ef->ed) | ||
545 | ef->ed->offset = strings_offset; | ||
546 | |||
547 | /* go thru and write the header */ | ||
548 | head[0] = (int)htonl((unsigned int)EET_MAGIC_FILE2); | ||
549 | head[1] = (int)htonl((unsigned int)num_directory_entries); | ||
550 | head[2] = (int)htonl((unsigned int)num_dictionary_entries); | ||
551 | |||
552 | fseek(fp, 0, SEEK_SET); | ||
553 | if (fwrite(head, sizeof (head), 1, fp) != 1) | ||
554 | goto write_error; | ||
555 | |||
556 | /* write directories entry */ | ||
557 | for (i = 0; i < num; i++) | ||
558 | { | ||
559 | for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) | ||
560 | { | ||
561 | unsigned int flag; | ||
562 | int ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT]; | ||
563 | |||
564 | flag = (efn->alias << 2) | (efn->ciphered << 1) | efn->compression; | ||
565 | |||
566 | ibuf[0] = (int)htonl((unsigned int)efn->offset); | ||
567 | ibuf[1] = (int)htonl((unsigned int)efn->size); | ||
568 | ibuf[2] = (int)htonl((unsigned int)efn->data_size); | ||
569 | ibuf[3] = (int)htonl((unsigned int)efn->name_offset); | ||
570 | ibuf[4] = (int)htonl((unsigned int)efn->name_size); | ||
571 | ibuf[5] = (int)htonl((unsigned int)flag); | ||
572 | |||
573 | if (fwrite(ibuf, sizeof(ibuf), 1, fp) != 1) | ||
574 | goto write_error; | ||
575 | } | ||
576 | } | ||
577 | |||
578 | /* write dictionary */ | ||
579 | if (ef->ed) | ||
580 | { | ||
581 | int offset = strings_offset; | ||
582 | |||
583 | for (j = 0; j < ef->ed->count; ++j) | ||
584 | { | ||
585 | int sbuf[EET_FILE2_DICTIONARY_ENTRY_COUNT]; | ||
586 | |||
587 | sbuf[0] = (int)htonl((unsigned int)ef->ed->all[j].hash); | ||
588 | sbuf[1] = (int)htonl((unsigned int)offset); | ||
589 | sbuf[2] = (int)htonl((unsigned int)ef->ed->all[j].len); | ||
590 | sbuf[3] = (int)htonl((unsigned int)ef->ed->all[j].prev); | ||
591 | sbuf[4] = (int)htonl((unsigned int)ef->ed->all[j].next); | ||
592 | |||
593 | offset += ef->ed->all[j].len; | ||
594 | |||
595 | if (fwrite(sbuf, sizeof (sbuf), 1, fp) != 1) | ||
596 | goto write_error; | ||
597 | } | ||
598 | } | ||
599 | |||
600 | /* write directories name */ | ||
601 | for (i = 0; i < num; i++) | ||
602 | { | ||
603 | for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) | ||
604 | { | ||
605 | if (fwrite(efn->name, efn->name_size, 1, fp) != 1) | ||
606 | goto write_error; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | /* write strings */ | ||
611 | if (ef->ed) | ||
612 | for (j = 0; j < ef->ed->count; ++j) | ||
613 | { | ||
614 | if (fwrite(ef->ed->all[j].str, ef->ed->all[j].len, 1, fp) != 1) | ||
615 | goto write_error; | ||
616 | } | ||
617 | |||
618 | /* write data */ | ||
619 | for (i = 0; i < num; i++) | ||
620 | { | ||
621 | for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) | ||
622 | { | ||
623 | if (fwrite(efn->data, efn->size, 1, fp) != 1) | ||
624 | goto write_error; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | /* flush all write to the file. */ | ||
629 | fflush(fp); | ||
630 | // this is going to really cause trouble. if ANYTHING this needs to go into a | ||
631 | // thread spawned off - but even then... | ||
632 | // in this case... ext4 is "wrong". (yes we can jump up and down and point posix | ||
633 | // manual pages at eachother, but ext4 broke behavior that has been in place | ||
634 | // for decades and that 1000's of apps rely on daily - that is that one operation | ||
635 | // to disk is committed to disk BEFORE following operations, so the fs retains | ||
636 | // a consistent state | ||
637 | // fsync(fileno(fp)); | ||
638 | |||
639 | /* append signature if required */ | ||
640 | if (ef->key) | ||
641 | { | ||
642 | error = eet_identity_sign(fp, ef->key); | ||
643 | if (error != EET_ERROR_NONE) | ||
644 | goto sign_error; | ||
645 | } | ||
646 | |||
647 | /* no more writes pending */ | ||
648 | ef->writes_pending = 0; | ||
649 | |||
650 | fclose(fp); | ||
651 | |||
652 | return EET_ERROR_NONE; | ||
653 | |||
654 | write_error: | ||
655 | if (ferror(fp)) | ||
656 | { | ||
657 | switch (errno) | ||
658 | { | ||
659 | case EFBIG: error = EET_ERROR_WRITE_ERROR_FILE_TOO_BIG; break; | ||
660 | |||
661 | case EIO: error = EET_ERROR_WRITE_ERROR_IO_ERROR; break; | ||
662 | |||
663 | case ENOSPC: error = EET_ERROR_WRITE_ERROR_OUT_OF_SPACE; break; | ||
664 | |||
665 | case EPIPE: error = EET_ERROR_WRITE_ERROR_FILE_CLOSED; break; | ||
666 | |||
667 | default: error = EET_ERROR_WRITE_ERROR; break; | ||
668 | } /* switch */ | ||
669 | } | ||
670 | |||
671 | sign_error: | ||
672 | fclose(fp); | ||
673 | return error; | ||
674 | } /* eet_flush2 */ | ||
675 | |||
676 | EAPI int | ||
677 | eet_init(void) | ||
678 | { | ||
679 | if (++eet_init_count != 1) | ||
680 | return eet_init_count; | ||
681 | |||
682 | if (!eina_init()) | ||
683 | { | ||
684 | fprintf(stderr, "Eet: Eina init failed"); | ||
685 | return --eet_init_count; | ||
686 | } | ||
687 | |||
688 | _eet_log_dom_global = eina_log_domain_register("eet", EET_DEFAULT_LOG_COLOR); | ||
689 | if (_eet_log_dom_global < 0) | ||
690 | { | ||
691 | EINA_LOG_ERR("Eet Can not create a general log domain."); | ||
692 | goto shutdown_eina; | ||
693 | } | ||
694 | |||
695 | eina_lock_new(&eet_cache_lock); | ||
696 | |||
697 | if (!eet_node_init()) | ||
698 | { | ||
699 | EINA_LOG_ERR("Eet: Eet_Node mempool creation failed"); | ||
700 | goto unregister_log_domain; | ||
701 | } | ||
702 | |||
703 | #ifdef HAVE_GNUTLS | ||
704 | /* Before the library can be used, it must initialize itself if needed. */ | ||
705 | if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0) | ||
706 | { | ||
707 | gcry_check_version(NULL); | ||
708 | /* Disable warning messages about problems with the secure memory subsystem. | ||
709 | This command should be run right after gcry_check_version. */ | ||
710 | if (gcry_control(GCRYCTL_DISABLE_SECMEM_WARN)) | ||
711 | goto shutdown_eet; /* This command is used to allocate a pool of secure memory and thus | ||
712 | enabling the use of secure memory. It also drops all extra privileges the | ||
713 | process has (i.e. if it is run as setuid (root)). If the argument nbytes | ||
714 | is 0, secure memory will be disabled. The minimum amount of secure memory | ||
715 | allocated is currently 16384 bytes; you may thus use a value of 1 to | ||
716 | request that default size. */ | ||
717 | |||
718 | if (gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0)) | ||
719 | WRN( | ||
720 | "BIG FAT WARNING: I AM UNABLE TO REQUEST SECMEM, Cryptographic operation are at risk !"); | ||
721 | } | ||
722 | |||
723 | # ifdef EINA_HAVE_THREADS | ||
724 | if (gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread)) | ||
725 | WRN( | ||
726 | "YOU ARE USING PTHREADS, BUT I CANNOT INITIALIZE THREADSAFE GCRYPT OPERATIONS!"); | ||
727 | |||
728 | # endif /* ifdef EINA_HAVE_THREADS */ | ||
729 | if (gnutls_global_init()) | ||
730 | goto shutdown_eet; | ||
731 | |||
732 | #endif /* ifdef HAVE_GNUTLS */ | ||
733 | #ifdef HAVE_OPENSSL | ||
734 | ERR_load_crypto_strings(); | ||
735 | OpenSSL_add_all_algorithms(); | ||
736 | #endif /* ifdef HAVE_OPENSSL */ | ||
737 | |||
738 | return eet_init_count; | ||
739 | |||
740 | #ifdef HAVE_GNUTLS | ||
741 | shutdown_eet: | ||
742 | #endif | ||
743 | eet_node_shutdown(); | ||
744 | unregister_log_domain: | ||
745 | eina_log_domain_unregister(_eet_log_dom_global); | ||
746 | _eet_log_dom_global = -1; | ||
747 | shutdown_eina: | ||
748 | eina_shutdown(); | ||
749 | return --eet_init_count; | ||
750 | } /* eet_init */ | ||
751 | |||
752 | EAPI int | ||
753 | eet_shutdown(void) | ||
754 | { | ||
755 | if (--eet_init_count != 0) | ||
756 | return eet_init_count; | ||
757 | |||
758 | eet_clearcache(); | ||
759 | eet_node_shutdown(); | ||
760 | |||
761 | eina_lock_free(&eet_cache_lock); | ||
762 | |||
763 | #ifdef HAVE_GNUTLS | ||
764 | gnutls_global_deinit(); | ||
765 | #endif /* ifdef HAVE_GNUTLS */ | ||
766 | #ifdef HAVE_OPENSSL | ||
767 | EVP_cleanup(); | ||
768 | ERR_free_strings(); | ||
769 | #endif /* ifdef HAVE_OPENSSL */ | ||
770 | eina_log_domain_unregister(_eet_log_dom_global); | ||
771 | _eet_log_dom_global = -1; | ||
772 | eina_shutdown(); | ||
773 | |||
774 | return eet_init_count; | ||
775 | } /* eet_shutdown */ | ||
776 | |||
777 | EAPI Eet_Error | ||
778 | eet_sync(Eet_File *ef) | ||
779 | { | ||
780 | Eet_Error ret; | ||
781 | |||
782 | if (eet_check_pointer(ef)) | ||
783 | return EET_ERROR_BAD_OBJECT; | ||
784 | |||
785 | if ((ef->mode != EET_FILE_MODE_WRITE) && | ||
786 | (ef->mode != EET_FILE_MODE_READ_WRITE)) | ||
787 | return EET_ERROR_NOT_WRITABLE; | ||
788 | |||
789 | if (!ef->writes_pending) | ||
790 | return EET_ERROR_NONE; | ||
791 | |||
792 | LOCK_FILE(ef); | ||
793 | |||
794 | ret = eet_flush2(ef); | ||
795 | |||
796 | UNLOCK_FILE(ef); | ||
797 | return ret; | ||
798 | } /* eet_sync */ | ||
799 | |||
800 | EAPI void | ||
801 | eet_clearcache(void) | ||
802 | { | ||
803 | int num = 0; | ||
804 | int i; | ||
805 | |||
806 | /* | ||
807 | * We need to compute the list of eet file to close separately from the cache, | ||
808 | * due to eet_close removing them from the cache after each call. | ||
809 | */ | ||
810 | LOCK_CACHE; | ||
811 | for (i = 0; i < eet_writers_num; i++) | ||
812 | { | ||
813 | if (eet_writers[i]->references <= 0) | ||
814 | num++; | ||
815 | } | ||
816 | |||
817 | for (i = 0; i < eet_readers_num; i++) | ||
818 | { | ||
819 | if (eet_readers[i]->references <= 0) | ||
820 | num++; | ||
821 | } | ||
822 | |||
823 | if (num > 0) | ||
824 | { | ||
825 | Eet_File **closelist = NULL; | ||
826 | |||
827 | closelist = alloca(num * sizeof(Eet_File *)); | ||
828 | num = 0; | ||
829 | for (i = 0; i < eet_writers_num; i++) | ||
830 | { | ||
831 | if (eet_writers[i]->references <= 0) | ||
832 | { | ||
833 | closelist[num] = eet_writers[i]; | ||
834 | eet_writers[i]->delete_me_now = 1; | ||
835 | num++; | ||
836 | } | ||
837 | } | ||
838 | |||
839 | for (i = 0; i < eet_readers_num; i++) | ||
840 | { | ||
841 | if (eet_readers[i]->references <= 0) | ||
842 | { | ||
843 | closelist[num] = eet_readers[i]; | ||
844 | eet_readers[i]->delete_me_now = 1; | ||
845 | num++; | ||
846 | } | ||
847 | } | ||
848 | |||
849 | for (i = 0; i < num; i++) | ||
850 | { | ||
851 | eet_internal_close(closelist[i], EINA_TRUE); | ||
852 | } | ||
853 | } | ||
854 | |||
855 | UNLOCK_CACHE; | ||
856 | } /* eet_clearcache */ | ||
857 | |||
858 | /* FIXME: MMAP race condition in READ_WRITE_MODE */ | ||
859 | static Eet_File * | ||
860 | eet_internal_read2(Eet_File *ef) | ||
861 | { | ||
862 | const int *data = (const int *)ef->data; | ||
863 | const char *start = (const char *)ef->data; | ||
864 | int idx = 0; | ||
865 | unsigned long int bytes_directory_entries; | ||
866 | unsigned long int bytes_dictionary_entries; | ||
867 | unsigned long int signature_base_offset; | ||
868 | unsigned long int num_directory_entries; | ||
869 | unsigned long int num_dictionary_entries; | ||
870 | unsigned int i; | ||
871 | |||
872 | idx += sizeof(int); | ||
873 | if (eet_test_close((int)ntohl(*data) != EET_MAGIC_FILE2, ef)) | ||
874 | return NULL; | ||
875 | |||
876 | data++; | ||
877 | |||
878 | #define GET_INT(Value, Pointer, Index) \ | ||
879 | { \ | ||
880 | Value = ntohl(*Pointer); \ | ||
881 | Pointer++; \ | ||
882 | Index += sizeof(int); \ | ||
883 | } | ||
884 | |||
885 | /* get entries count and byte count */ | ||
886 | GET_INT(num_directory_entries, data, idx); | ||
887 | /* get dictionary count and byte count */ | ||
888 | GET_INT(num_dictionary_entries, data, idx); | ||
889 | |||
890 | bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * | ||
891 | num_directory_entries + EET_FILE2_HEADER_SIZE; | ||
892 | bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * | ||
893 | num_dictionary_entries; | ||
894 | |||
895 | /* we can't have > 0x7fffffff values here - invalid */ | ||
896 | if (eet_test_close((num_directory_entries > 0x7fffffff), ef)) | ||
897 | return NULL; | ||
898 | |||
899 | /* we can't have more bytes directory and bytes in dictionaries than the size of the file */ | ||
900 | if (eet_test_close((bytes_directory_entries + bytes_dictionary_entries) > | ||
901 | ef->data_size, ef)) | ||
902 | return NULL; | ||
903 | |||
904 | /* allocate header */ | ||
905 | ef->header = calloc(1, sizeof(Eet_File_Header)); | ||
906 | if (eet_test_close(!ef->header, ef)) | ||
907 | return NULL; | ||
908 | |||
909 | ef->header->magic = EET_MAGIC_FILE_HEADER; | ||
910 | |||
911 | /* allocate directory block in ram */ | ||
912 | ef->header->directory = calloc(1, sizeof(Eet_File_Directory)); | ||
913 | if (eet_test_close(!ef->header->directory, ef)) | ||
914 | return NULL; | ||
915 | |||
916 | /* 8 bit hash table (256 buckets) */ | ||
917 | ef->header->directory->size = 8; | ||
918 | /* allocate base hash table */ | ||
919 | ef->header->directory->nodes = | ||
920 | calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size)); | ||
921 | if (eet_test_close(!ef->header->directory->nodes, ef)) | ||
922 | return NULL; | ||
923 | |||
924 | signature_base_offset = 0; | ||
925 | if (num_directory_entries == 0) | ||
926 | { | ||
927 | signature_base_offset = ef->data_size; | ||
928 | } | ||
929 | |||
930 | /* actually read the directory block - all of it, into ram */ | ||
931 | for (i = 0; i < num_directory_entries; ++i) | ||
932 | { | ||
933 | const char *name; | ||
934 | Eet_File_Node *efn; | ||
935 | unsigned long int name_offset; | ||
936 | unsigned long int name_size; | ||
937 | int hash; | ||
938 | int flag; | ||
939 | |||
940 | /* out directory block is inconsistent - we have overrun our */ | ||
941 | /* dynamic block buffer before we finished scanning dir entries */ | ||
942 | efn = malloc(sizeof(Eet_File_Node)); | ||
943 | if (eet_test_close(!efn, ef)) | ||
944 | { | ||
945 | if (efn) free(efn); /* yes i know - we only get here if | ||
946 | * efn is null/0 -> trying to shut up | ||
947 | * warning tools like cppcheck */ | ||
948 | return NULL; | ||
949 | } | ||
950 | |||
951 | /* get entrie header */ | ||
952 | GET_INT(efn->offset, data, idx); | ||
953 | GET_INT(efn->size, data, idx); | ||
954 | GET_INT(efn->data_size, data, idx); | ||
955 | GET_INT(name_offset, data, idx); | ||
956 | GET_INT(name_size, data, idx); | ||
957 | GET_INT(flag, data, idx); | ||
958 | |||
959 | efn->compression = flag & 0x1 ? 1 : 0; | ||
960 | efn->ciphered = flag & 0x2 ? 1 : 0; | ||
961 | efn->alias = flag & 0x4 ? 1 : 0; | ||
962 | |||
963 | #define EFN_TEST(Test, Ef, Efn) \ | ||
964 | if (eet_test_close(Test, Ef)) \ | ||
965 | { \ | ||
966 | free(Efn); \ | ||
967 | return NULL; \ | ||
968 | } | ||
969 | |||
970 | /* check data pointer position */ | ||
971 | EFN_TEST(!((efn->size > 0) | ||
972 | && (efn->offset + efn->size <= ef->data_size) | ||
973 | && (efn->offset > bytes_dictionary_entries + | ||
974 | bytes_directory_entries)), ef, efn); | ||
975 | |||
976 | /* check name position */ | ||
977 | EFN_TEST(!((name_size > 0) | ||
978 | && (name_offset + name_size < ef->data_size) | ||
979 | && (name_offset >= bytes_dictionary_entries + | ||
980 | bytes_directory_entries)), ef, efn); | ||
981 | |||
982 | name = start + name_offset; | ||
983 | |||
984 | /* check '\0' at the end of name string */ | ||
985 | EFN_TEST(name[name_size - 1] != '\0', ef, efn); | ||
986 | |||
987 | efn->free_name = 0; | ||
988 | efn->name = (char *)name; | ||
989 | efn->name_size = name_size; | ||
990 | |||
991 | hash = _eet_hash_gen(efn->name, ef->header->directory->size); | ||
992 | efn->next = ef->header->directory->nodes[hash]; | ||
993 | ef->header->directory->nodes[hash] = efn; | ||
994 | |||
995 | /* read-only mode, so currently we have no data loaded */ | ||
996 | if (ef->mode == EET_FILE_MODE_READ) | ||
997 | efn->data = NULL; /* read-write mode - read everything into ram */ | ||
998 | else | ||
999 | { | ||
1000 | efn->data = malloc(efn->size); | ||
1001 | if (efn->data) | ||
1002 | memcpy(efn->data, ef->data + efn->offset, efn->size); | ||
1003 | } | ||
1004 | |||
1005 | /* compute the possible position of a signature */ | ||
1006 | if (signature_base_offset < efn->offset + efn->size) | ||
1007 | signature_base_offset = efn->offset + efn->size; | ||
1008 | } | ||
1009 | |||
1010 | ef->ed = NULL; | ||
1011 | |||
1012 | if (num_dictionary_entries) | ||
1013 | { | ||
1014 | const int *dico = (const int *)ef->data + | ||
1015 | EET_FILE2_DIRECTORY_ENTRY_COUNT * num_directory_entries + | ||
1016 | EET_FILE2_HEADER_COUNT; | ||
1017 | int j; | ||
1018 | |||
1019 | if (eet_test_close((num_dictionary_entries * | ||
1020 | (int)EET_FILE2_DICTIONARY_ENTRY_SIZE + idx) > | ||
1021 | (bytes_dictionary_entries + bytes_directory_entries), | ||
1022 | ef)) | ||
1023 | return NULL; | ||
1024 | |||
1025 | ef->ed = calloc(1, sizeof (Eet_Dictionary)); | ||
1026 | if (eet_test_close(!ef->ed, ef)) | ||
1027 | return NULL; | ||
1028 | |||
1029 | ef->ed->all = calloc(num_dictionary_entries, sizeof (Eet_String)); | ||
1030 | if (eet_test_close(!ef->ed->all, ef)) | ||
1031 | return NULL; | ||
1032 | |||
1033 | ef->ed->count = num_dictionary_entries; | ||
1034 | ef->ed->total = num_dictionary_entries; | ||
1035 | ef->ed->start = start + bytes_dictionary_entries + | ||
1036 | bytes_directory_entries; | ||
1037 | ef->ed->end = ef->ed->start; | ||
1038 | |||
1039 | for (j = 0; j < ef->ed->count; ++j) | ||
1040 | { | ||
1041 | unsigned int offset; | ||
1042 | int hash; | ||
1043 | |||
1044 | GET_INT(hash, dico, idx); | ||
1045 | GET_INT(offset, dico, idx); | ||
1046 | GET_INT(ef->ed->all[j].len, dico, idx); | ||
1047 | GET_INT(ef->ed->all[j].prev, dico, idx); | ||
1048 | GET_INT(ef->ed->all[j].next, dico, idx); | ||
1049 | |||
1050 | /* Hash value could be stored on 8bits data, but this will break alignment of all the others data. | ||
1051 | So stick to int and check the value. */ | ||
1052 | if (eet_test_close(hash & 0xFFFFFF00, ef)) | ||
1053 | return NULL; | ||
1054 | |||
1055 | /* Check string position */ | ||
1056 | if (eet_test_close(!((ef->ed->all[j].len > 0) | ||
1057 | && (offset > | ||
1058 | (bytes_dictionary_entries + | ||
1059 | bytes_directory_entries)) | ||
1060 | && (offset + ef->ed->all[j].len < | ||
1061 | ef->data_size)), ef)) | ||
1062 | return NULL; | ||
1063 | |||
1064 | ef->ed->all[j].str = start + offset; | ||
1065 | |||
1066 | if (ef->ed->all[j].str + ef->ed->all[j].len > ef->ed->end) | ||
1067 | ef->ed->end = ef->ed->all[j].str + ef->ed->all[j].len; | ||
1068 | |||
1069 | /* Check '\0' at the end of the string */ | ||
1070 | if (eet_test_close(ef->ed->all[j].str[ef->ed->all[j].len - 1] != | ||
1071 | '\0', ef)) | ||
1072 | return NULL; | ||
1073 | |||
1074 | ef->ed->all[j].hash = hash; | ||
1075 | if (ef->ed->all[j].prev == -1) | ||
1076 | ef->ed->hash[hash] = j; | ||
1077 | |||
1078 | /* compute the possible position of a signature */ | ||
1079 | if (signature_base_offset < offset + ef->ed->all[j].len) | ||
1080 | signature_base_offset = offset + ef->ed->all[j].len; | ||
1081 | } | ||
1082 | } | ||
1083 | |||
1084 | /* Check if the file is signed */ | ||
1085 | ef->x509_der = NULL; | ||
1086 | ef->x509_length = 0; | ||
1087 | ef->signature = NULL; | ||
1088 | ef->signature_length = 0; | ||
1089 | |||
1090 | if (signature_base_offset < ef->data_size) | ||
1091 | { | ||
1092 | #ifdef HAVE_SIGNATURE | ||
1093 | const unsigned char *buffer = ((const unsigned char *)ef->data) + | ||
1094 | signature_base_offset; | ||
1095 | ef->x509_der = eet_identity_check(ef->data, | ||
1096 | signature_base_offset, | ||
1097 | &ef->sha1, | ||
1098 | &ef->sha1_length, | ||
1099 | buffer, | ||
1100 | ef->data_size - signature_base_offset, | ||
1101 | &ef->signature, | ||
1102 | &ef->signature_length, | ||
1103 | &ef->x509_length); | ||
1104 | |||
1105 | if (eet_test_close(!ef->x509_der, ef)) | ||
1106 | return NULL; | ||
1107 | |||
1108 | #else /* ifdef HAVE_SIGNATURE */ | ||
1109 | ERR( | ||
1110 | "This file could be signed but you didn't compile the necessary code to check the signature."); | ||
1111 | #endif /* ifdef HAVE_SIGNATURE */ | ||
1112 | } | ||
1113 | |||
1114 | return ef; | ||
1115 | } /* eet_internal_read2 */ | ||
1116 | |||
1117 | #if EET_OLD_EET_FILE_FORMAT | ||
1118 | static Eet_File * | ||
1119 | eet_internal_read1(Eet_File *ef) | ||
1120 | { | ||
1121 | const unsigned char *dyn_buf = NULL; | ||
1122 | const unsigned char *p = NULL; | ||
1123 | unsigned long int byte_entries; | ||
1124 | unsigned long int num_entries; | ||
1125 | unsigned int i; | ||
1126 | int idx = 0; | ||
1127 | |||
1128 | WRN( | ||
1129 | "EET file format of '%s' is deprecated. You should just open it one time with mode == EET_FILE_MODE_READ_WRITE to solve this issue.", | ||
1130 | ef->path); | ||
1131 | |||
1132 | /* build header table if read mode */ | ||
1133 | /* geat header */ | ||
1134 | idx += sizeof(int); | ||
1135 | if (eet_test_close((int)ntohl(*((int *)ef->data)) != EET_MAGIC_FILE, ef)) | ||
1136 | return NULL; | ||
1137 | |||
1138 | #define EXTRACT_INT(Value, Pointer, Index) \ | ||
1139 | { \ | ||
1140 | int tmp; \ | ||
1141 | memcpy(&tmp, Pointer + Index, sizeof(int)); \ | ||
1142 | Value = ntohl(tmp); \ | ||
1143 | Index += sizeof(int); \ | ||
1144 | } | ||
1145 | |||
1146 | /* get entries count and byte count */ | ||
1147 | EXTRACT_INT(num_entries, ef->data, idx); | ||
1148 | EXTRACT_INT(byte_entries, ef->data, idx); | ||
1149 | |||
1150 | /* we can't have <= 0 values here - invalid */ | ||
1151 | if (eet_test_close((num_entries > 0x7fffffff) || | ||
1152 | (byte_entries > 0x7fffffff), ef)) | ||
1153 | return NULL; | ||
1154 | |||
1155 | /* we can't have more entires than minimum bytes for those! invalid! */ | ||
1156 | if (eet_test_close((num_entries * 20) > byte_entries, ef)) | ||
1157 | return NULL; | ||
1158 | |||
1159 | /* check we will not outrun the file limit */ | ||
1160 | if (eet_test_close(((byte_entries + (int)(sizeof(int) * 3)) > | ||
1161 | ef->data_size), ef)) | ||
1162 | return NULL; | ||
1163 | |||
1164 | /* allocate header */ | ||
1165 | ef->header = calloc(1, sizeof(Eet_File_Header)); | ||
1166 | if (eet_test_close(!ef->header, ef)) | ||
1167 | return NULL; | ||
1168 | |||
1169 | ef->header->magic = EET_MAGIC_FILE_HEADER; | ||
1170 | |||
1171 | /* allocate directory block in ram */ | ||
1172 | ef->header->directory = calloc(1, sizeof(Eet_File_Directory)); | ||
1173 | if (eet_test_close(!ef->header->directory, ef)) | ||
1174 | return NULL; | ||
1175 | |||
1176 | /* 8 bit hash table (256 buckets) */ | ||
1177 | ef->header->directory->size = 8; | ||
1178 | /* allocate base hash table */ | ||
1179 | ef->header->directory->nodes = | ||
1180 | calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size)); | ||
1181 | if (eet_test_close(!ef->header->directory->nodes, ef)) | ||
1182 | return NULL; | ||
1183 | |||
1184 | /* actually read the directory block - all of it, into ram */ | ||
1185 | dyn_buf = ef->data + idx; | ||
1186 | |||
1187 | /* parse directory block */ | ||
1188 | p = dyn_buf; | ||
1189 | |||
1190 | for (i = 0; i < num_entries; i++) | ||
1191 | { | ||
1192 | Eet_File_Node *efn; | ||
1193 | void *data = NULL; | ||
1194 | int indexn = 0; | ||
1195 | int name_size; | ||
1196 | int hash; | ||
1197 | int k; | ||
1198 | |||
1199 | #define HEADER_SIZE (sizeof(int) * 5) | ||
1200 | |||
1201 | /* out directory block is inconsistent - we have overrun our */ | ||
1202 | /* dynamic block buffer before we finished scanning dir entries */ | ||
1203 | if (eet_test_close(p + HEADER_SIZE >= (dyn_buf + byte_entries), ef)) | ||
1204 | return NULL; | ||
1205 | |||
1206 | /* allocate all the ram needed for this stored node accounting */ | ||
1207 | efn = malloc (sizeof(Eet_File_Node)); | ||
1208 | if (eet_test_close(!efn, ef)) | ||
1209 | { | ||
1210 | if (efn) free(efn); /* yes i know - we only get here if | ||
1211 | * efn is null/0 -> trying to shut up | ||
1212 | * warning tools like cppcheck */ | ||
1213 | return NULL; | ||
1214 | } | ||
1215 | |||
1216 | /* get entrie header */ | ||
1217 | EXTRACT_INT(efn->offset, p, indexn); | ||
1218 | EXTRACT_INT(efn->compression, p, indexn); | ||
1219 | EXTRACT_INT(efn->size, p, indexn); | ||
1220 | EXTRACT_INT(efn->data_size, p, indexn); | ||
1221 | EXTRACT_INT(name_size, p, indexn); | ||
1222 | |||
1223 | efn->name_size = name_size; | ||
1224 | efn->ciphered = 0; | ||
1225 | efn->alias = 0; | ||
1226 | |||
1227 | /* invalid size */ | ||
1228 | if (eet_test_close(efn->size <= 0, ef)) | ||
1229 | { | ||
1230 | free(efn); | ||
1231 | return NULL; | ||
1232 | } | ||
1233 | |||
1234 | /* invalid name_size */ | ||
1235 | if (eet_test_close(name_size <= 0, ef)) | ||
1236 | { | ||
1237 | free(efn); | ||
1238 | return NULL; | ||
1239 | } | ||
1240 | |||
1241 | /* reading name would mean falling off end of dyn_buf - invalid */ | ||
1242 | if (eet_test_close((p + 16 + name_size) > (dyn_buf + byte_entries), ef)) | ||
1243 | { | ||
1244 | free(efn); | ||
1245 | return NULL; | ||
1246 | } | ||
1247 | |||
1248 | /* This code is useless if we dont want backward compatibility */ | ||
1249 | for (k = name_size; | ||
1250 | k > 0 && ((unsigned char)*(p + HEADER_SIZE + k)) != 0; --k) | ||
1251 | ; | ||
1252 | |||
1253 | efn->free_name = ((unsigned char)*(p + HEADER_SIZE + k)) != 0; | ||
1254 | |||
1255 | if (efn->free_name) | ||
1256 | { | ||
1257 | efn->name = malloc(sizeof(char) * name_size + 1); | ||
1258 | if (eet_test_close(!efn->name, ef)) | ||
1259 | { | ||
1260 | free(efn); | ||
1261 | return NULL; | ||
1262 | } | ||
1263 | |||
1264 | strncpy(efn->name, (char *)p + HEADER_SIZE, name_size); | ||
1265 | efn->name[name_size] = 0; | ||
1266 | |||
1267 | WRN( | ||
1268 | "File: %s is not up to date for key \"%s\" - needs rebuilding sometime", | ||
1269 | ef->path, | ||
1270 | efn->name); | ||
1271 | } | ||
1272 | else | ||
1273 | /* The only really useful peace of code for efn->name (no backward compatibility) */ | ||
1274 | efn->name = (char *)((unsigned char *)(p + HEADER_SIZE)); | ||
1275 | |||
1276 | /* get hash bucket it should go in */ | ||
1277 | hash = _eet_hash_gen(efn->name, ef->header->directory->size); | ||
1278 | efn->next = ef->header->directory->nodes[hash]; | ||
1279 | ef->header->directory->nodes[hash] = efn; | ||
1280 | |||
1281 | /* read-only mode, so currently we have no data loaded */ | ||
1282 | if (ef->mode == EET_FILE_MODE_READ) | ||
1283 | efn->data = NULL; /* read-write mode - read everything into ram */ | ||
1284 | else | ||
1285 | { | ||
1286 | data = malloc(efn->size); | ||
1287 | if (data) | ||
1288 | memcpy(data, ef->data + efn->offset, efn->size); | ||
1289 | |||
1290 | efn->data = data; | ||
1291 | } | ||
1292 | |||
1293 | /* advance */ | ||
1294 | p += HEADER_SIZE + name_size; | ||
1295 | } | ||
1296 | return ef; | ||
1297 | } /* eet_internal_read1 */ | ||
1298 | |||
1299 | #endif /* if EET_OLD_EET_FILE_FORMAT */ | ||
1300 | |||
1301 | /* | ||
1302 | * this should only be called when the cache lock is already held | ||
1303 | * (We could drop this restriction if we add a parameter to eet_test_close | ||
1304 | * that indicates if the lock is held or not. For now it is easiest | ||
1305 | * to just require that it is always held.) | ||
1306 | */ | ||
1307 | static Eet_File * | ||
1308 | eet_internal_read(Eet_File *ef) | ||
1309 | { | ||
1310 | const int *data = (const int *)ef->data; | ||
1311 | |||
1312 | if (eet_test_close((ef->data == (void *)-1) || (!ef->data), ef)) | ||
1313 | return NULL; | ||
1314 | |||
1315 | if (eet_test_close(ef->data_size < (int)sizeof(int) * 3, ef)) | ||
1316 | return NULL; | ||
1317 | |||
1318 | switch (ntohl(*data)) | ||
1319 | { | ||
1320 | #if EET_OLD_EET_FILE_FORMAT | ||
1321 | case EET_MAGIC_FILE: | ||
1322 | return eet_internal_read1(ef); | ||
1323 | |||
1324 | #endif /* if EET_OLD_EET_FILE_FORMAT */ | ||
1325 | case EET_MAGIC_FILE2: | ||
1326 | return eet_internal_read2(ef); | ||
1327 | |||
1328 | default: | ||
1329 | ef->delete_me_now = 1; | ||
1330 | eet_internal_close(ef, EINA_TRUE); | ||
1331 | break; | ||
1332 | } /* switch */ | ||
1333 | |||
1334 | return NULL; | ||
1335 | } /* eet_internal_read */ | ||
1336 | |||
1337 | static Eet_Error | ||
1338 | eet_internal_close(Eet_File *ef, | ||
1339 | Eina_Bool locked) | ||
1340 | { | ||
1341 | Eet_Error err; | ||
1342 | |||
1343 | /* check to see its' an eet file pointer */ | ||
1344 | if (eet_check_pointer(ef)) | ||
1345 | return EET_ERROR_BAD_OBJECT; | ||
1346 | |||
1347 | if (!locked) | ||
1348 | LOCK_CACHE; | ||
1349 | |||
1350 | /* deref */ | ||
1351 | ef->references--; | ||
1352 | /* if its still referenced - dont go any further */ | ||
1353 | if (ef->references > 0) | ||
1354 | { | ||
1355 | /* flush any writes */ | ||
1356 | if ((ef->mode == EET_FILE_MODE_WRITE) || | ||
1357 | (ef->mode == EET_FILE_MODE_READ_WRITE)) | ||
1358 | eet_sync(ef); | ||
1359 | goto on_error; | ||
1360 | } | ||
1361 | |||
1362 | err = eet_flush2(ef); | ||
1363 | |||
1364 | eet_identity_unref(ef->key); | ||
1365 | ef->key = NULL; | ||
1366 | |||
1367 | /* if not urgent to delete it - dont free it - leave it in cache */ | ||
1368 | if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ)) | ||
1369 | goto on_error; | ||
1370 | |||
1371 | /* remove from cache */ | ||
1372 | if (ef->mode == EET_FILE_MODE_READ) | ||
1373 | eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc); | ||
1374 | else if ((ef->mode == EET_FILE_MODE_WRITE) || | ||
1375 | (ef->mode == EET_FILE_MODE_READ_WRITE)) | ||
1376 | eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc); | ||
1377 | |||
1378 | /* we can unlock the cache now */ | ||
1379 | if (!locked) | ||
1380 | UNLOCK_CACHE; | ||
1381 | |||
1382 | DESTROY_FILE(ef); | ||
1383 | |||
1384 | /* free up data */ | ||
1385 | if (ef->header) | ||
1386 | { | ||
1387 | if (ef->header->directory) | ||
1388 | { | ||
1389 | if (ef->header->directory->nodes) | ||
1390 | { | ||
1391 | int i, num; | ||
1392 | |||
1393 | num = (1 << ef->header->directory->size); | ||
1394 | for (i = 0; i < num; i++) | ||
1395 | { | ||
1396 | Eet_File_Node *efn; | ||
1397 | |||
1398 | while ((efn = ef->header->directory->nodes[i])) | ||
1399 | { | ||
1400 | if (efn->data) | ||
1401 | free(efn->data); | ||
1402 | |||
1403 | ef->header->directory->nodes[i] = efn->next; | ||
1404 | |||
1405 | if (efn->free_name) | ||
1406 | free(efn->name); | ||
1407 | |||
1408 | free(efn); | ||
1409 | } | ||
1410 | } | ||
1411 | free(ef->header->directory->nodes); | ||
1412 | } | ||
1413 | |||
1414 | free(ef->header->directory); | ||
1415 | } | ||
1416 | |||
1417 | free(ef->header); | ||
1418 | } | ||
1419 | |||
1420 | eet_dictionary_free(ef->ed); | ||
1421 | |||
1422 | if (ef->sha1) | ||
1423 | free(ef->sha1); | ||
1424 | |||
1425 | if (ef->readfp) | ||
1426 | { | ||
1427 | if (ef->data) | ||
1428 | eina_file_map_free(ef->readfp, (void *)ef->data); | ||
1429 | |||
1430 | eina_file_close(ef->readfp); | ||
1431 | } | ||
1432 | |||
1433 | /* zero out ram for struct - caution tactic against stale memory use */ | ||
1434 | memset(ef, 0, sizeof(Eet_File)); | ||
1435 | |||
1436 | /* free it */ | ||
1437 | free(ef); | ||
1438 | return err; | ||
1439 | |||
1440 | on_error: | ||
1441 | if (!locked) | ||
1442 | UNLOCK_CACHE; | ||
1443 | |||
1444 | return EET_ERROR_NONE; | ||
1445 | } /* eet_internal_close */ | ||
1446 | |||
1447 | EAPI Eet_File * | ||
1448 | eet_memopen_read(const void *data, | ||
1449 | size_t size) | ||
1450 | { | ||
1451 | Eet_File *ef; | ||
1452 | |||
1453 | if (!data || size == 0) | ||
1454 | return NULL; | ||
1455 | |||
1456 | ef = malloc (sizeof (Eet_File)); | ||
1457 | if (!ef) | ||
1458 | return NULL; | ||
1459 | |||
1460 | INIT_FILE(ef); | ||
1461 | ef->ed = NULL; | ||
1462 | ef->path = NULL; | ||
1463 | ef->key = NULL; | ||
1464 | ef->magic = EET_MAGIC_FILE; | ||
1465 | ef->references = 1; | ||
1466 | ef->mode = EET_FILE_MODE_READ; | ||
1467 | ef->header = NULL; | ||
1468 | ef->delete_me_now = 1; | ||
1469 | ef->readfp = NULL; | ||
1470 | ef->data = data; | ||
1471 | ef->data_size = size; | ||
1472 | ef->sha1 = NULL; | ||
1473 | ef->sha1_length = 0; | ||
1474 | |||
1475 | /* eet_internal_read expects the cache lock to be held when it is called */ | ||
1476 | LOCK_CACHE; | ||
1477 | ef = eet_internal_read(ef); | ||
1478 | UNLOCK_CACHE; | ||
1479 | return ef; | ||
1480 | } /* eet_memopen_read */ | ||
1481 | |||
1482 | EAPI Eet_File * | ||
1483 | eet_open(const char *file, | ||
1484 | Eet_File_Mode mode) | ||
1485 | { | ||
1486 | Eina_File *fp; | ||
1487 | Eet_File *ef; | ||
1488 | int file_len; | ||
1489 | unsigned long int size; | ||
1490 | |||
1491 | if (!file) | ||
1492 | return NULL; | ||
1493 | |||
1494 | /* find the current file handle in cache*/ | ||
1495 | ef = NULL; | ||
1496 | LOCK_CACHE; | ||
1497 | if (mode == EET_FILE_MODE_READ) | ||
1498 | { | ||
1499 | ef = eet_cache_find((char *)file, eet_writers, eet_writers_num); | ||
1500 | if (ef) | ||
1501 | { | ||
1502 | eet_sync(ef); | ||
1503 | ef->references++; | ||
1504 | ef->delete_me_now = 1; | ||
1505 | eet_internal_close(ef, EINA_TRUE); | ||
1506 | } | ||
1507 | |||
1508 | ef = eet_cache_find((char *)file, eet_readers, eet_readers_num); | ||
1509 | } | ||
1510 | else if ((mode == EET_FILE_MODE_WRITE) || | ||
1511 | (mode == EET_FILE_MODE_READ_WRITE)) | ||
1512 | { | ||
1513 | ef = eet_cache_find((char *)file, eet_readers, eet_readers_num); | ||
1514 | if (ef) | ||
1515 | { | ||
1516 | ef->delete_me_now = 1; | ||
1517 | ef->references++; | ||
1518 | eet_internal_close(ef, EINA_TRUE); | ||
1519 | } | ||
1520 | |||
1521 | ef = eet_cache_find((char *)file, eet_writers, eet_writers_num); | ||
1522 | } | ||
1523 | |||
1524 | /* try open the file based on mode */ | ||
1525 | if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE)) | ||
1526 | { | ||
1527 | /* Prevent garbage in futur comparison. */ | ||
1528 | fp = eina_file_open(file, EINA_FALSE); | ||
1529 | if (!fp) | ||
1530 | goto open_error; | ||
1531 | |||
1532 | size = eina_file_size_get(fp); | ||
1533 | |||
1534 | if (size < ((int)sizeof(int) * 3)) | ||
1535 | { | ||
1536 | eina_file_close(fp); | ||
1537 | fp = NULL; | ||
1538 | |||
1539 | size = 0; | ||
1540 | |||
1541 | goto open_error; | ||
1542 | } | ||
1543 | |||
1544 | open_error: | ||
1545 | if (!fp && mode == EET_FILE_MODE_READ) | ||
1546 | goto on_error; | ||
1547 | } | ||
1548 | else | ||
1549 | { | ||
1550 | if (mode != EET_FILE_MODE_WRITE) | ||
1551 | return NULL; | ||
1552 | |||
1553 | size = 0; | ||
1554 | |||
1555 | fp = NULL; | ||
1556 | } | ||
1557 | |||
1558 | /* We found one */ | ||
1559 | if (ef && ef->readfp != fp) | ||
1560 | { | ||
1561 | ef->delete_me_now = 1; | ||
1562 | ef->references++; | ||
1563 | eet_internal_close(ef, EINA_TRUE); | ||
1564 | ef = NULL; | ||
1565 | } | ||
1566 | |||
1567 | if (ef) | ||
1568 | { | ||
1569 | /* reference it up and return it */ | ||
1570 | if (fp) | ||
1571 | eina_file_close(fp); | ||
1572 | |||
1573 | ef->references++; | ||
1574 | UNLOCK_CACHE; | ||
1575 | return ef; | ||
1576 | } | ||
1577 | |||
1578 | file_len = strlen(file) + 1; | ||
1579 | |||
1580 | /* Allocate struct for eet file and have it zero'd out */ | ||
1581 | ef = malloc(sizeof(Eet_File) + file_len); | ||
1582 | if (!ef) | ||
1583 | goto on_error; | ||
1584 | |||
1585 | /* fill some of the members */ | ||
1586 | INIT_FILE(ef); | ||
1587 | ef->key = NULL; | ||
1588 | ef->readfp = fp; | ||
1589 | ef->path = ((char *)ef) + sizeof(Eet_File); | ||
1590 | memcpy(ef->path, file, file_len); | ||
1591 | ef->magic = EET_MAGIC_FILE; | ||
1592 | ef->references = 1; | ||
1593 | ef->mode = mode; | ||
1594 | ef->header = NULL; | ||
1595 | ef->writes_pending = 0; | ||
1596 | ef->delete_me_now = 0; | ||
1597 | ef->data = NULL; | ||
1598 | ef->data_size = 0; | ||
1599 | ef->sha1 = NULL; | ||
1600 | ef->sha1_length = 0; | ||
1601 | |||
1602 | ef->ed = (mode == EET_FILE_MODE_WRITE) | ||
1603 | || (!ef->readfp && mode == EET_FILE_MODE_READ_WRITE) ? | ||
1604 | eet_dictionary_add() : NULL; | ||
1605 | |||
1606 | if (!ef->readfp && | ||
1607 | (mode == EET_FILE_MODE_READ_WRITE || mode == EET_FILE_MODE_WRITE)) | ||
1608 | goto empty_file; | ||
1609 | |||
1610 | /* if we can't open - bail out */ | ||
1611 | if (eet_test_close(!ef->readfp, ef)) | ||
1612 | goto on_error; | ||
1613 | |||
1614 | /* if we opened for read or read-write */ | ||
1615 | if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE)) | ||
1616 | { | ||
1617 | ef->data_size = size; | ||
1618 | ef->data = eina_file_map_all(fp, EINA_FILE_SEQUENTIAL); | ||
1619 | if (eet_test_close((ef->data == NULL), ef)) | ||
1620 | goto on_error; | ||
1621 | |||
1622 | ef = eet_internal_read(ef); | ||
1623 | if (!ef) | ||
1624 | goto on_error; | ||
1625 | } | ||
1626 | |||
1627 | empty_file: | ||
1628 | /* add to cache */ | ||
1629 | if (ef->references == 1) | ||
1630 | { | ||
1631 | if (ef->mode == EET_FILE_MODE_READ) | ||
1632 | eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc); | ||
1633 | else if ((ef->mode == EET_FILE_MODE_WRITE) || | ||
1634 | (ef->mode == EET_FILE_MODE_READ_WRITE)) | ||
1635 | eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc); | ||
1636 | } | ||
1637 | |||
1638 | UNLOCK_CACHE; | ||
1639 | return ef; | ||
1640 | |||
1641 | on_error: | ||
1642 | UNLOCK_CACHE; | ||
1643 | return NULL; | ||
1644 | } /* eet_open */ | ||
1645 | |||
1646 | EAPI Eet_File_Mode | ||
1647 | eet_mode_get(Eet_File *ef) | ||
1648 | { | ||
1649 | /* check to see its' an eet file pointer */ | ||
1650 | if ((!ef) || (ef->magic != EET_MAGIC_FILE)) | ||
1651 | return EET_FILE_MODE_INVALID; | ||
1652 | else | ||
1653 | return ef->mode; | ||
1654 | } /* eet_mode_get */ | ||
1655 | |||
1656 | EAPI const void * | ||
1657 | eet_identity_x509(Eet_File *ef, | ||
1658 | int *der_length) | ||
1659 | { | ||
1660 | if (!ef->x509_der) | ||
1661 | return NULL; | ||
1662 | |||
1663 | if (der_length) | ||
1664 | *der_length = ef->x509_length; | ||
1665 | |||
1666 | return ef->x509_der; | ||
1667 | } /* eet_identity_x509 */ | ||
1668 | |||
1669 | EAPI const void * | ||
1670 | eet_identity_signature(Eet_File *ef, | ||
1671 | int *signature_length) | ||
1672 | { | ||
1673 | if (!ef->signature) | ||
1674 | return NULL; | ||
1675 | |||
1676 | if (signature_length) | ||
1677 | *signature_length = ef->signature_length; | ||
1678 | |||
1679 | return ef->signature; | ||
1680 | } /* eet_identity_signature */ | ||
1681 | |||
1682 | EAPI const void * | ||
1683 | eet_identity_sha1(Eet_File *ef, | ||
1684 | int *sha1_length) | ||
1685 | { | ||
1686 | if (!ef->sha1) | ||
1687 | ef->sha1 = eet_identity_compute_sha1(ef->data, | ||
1688 | ef->data_size, | ||
1689 | &ef->sha1_length); | ||
1690 | |||
1691 | if (sha1_length) | ||
1692 | *sha1_length = ef->sha1_length; | ||
1693 | |||
1694 | return ef->sha1; | ||
1695 | } /* eet_identity_sha1 */ | ||
1696 | |||
1697 | EAPI Eet_Error | ||
1698 | eet_identity_set(Eet_File *ef, | ||
1699 | Eet_Key *key) | ||
1700 | { | ||
1701 | Eet_Key *tmp; | ||
1702 | |||
1703 | if (!ef) | ||
1704 | return EET_ERROR_BAD_OBJECT; | ||
1705 | |||
1706 | tmp = ef->key; | ||
1707 | ef->key = key; | ||
1708 | eet_identity_ref(ef->key); | ||
1709 | eet_identity_unref(tmp); | ||
1710 | |||
1711 | /* flags that writes are pending */ | ||
1712 | ef->writes_pending = 1; | ||
1713 | |||
1714 | return EET_ERROR_NONE; | ||
1715 | } /* eet_identity_set */ | ||
1716 | |||
1717 | EAPI Eet_Error | ||
1718 | eet_close(Eet_File *ef) | ||
1719 | { | ||
1720 | return eet_internal_close(ef, EINA_FALSE); | ||
1721 | } /* eet_close */ | ||
1722 | |||
1723 | EAPI void * | ||
1724 | eet_read_cipher(Eet_File *ef, | ||
1725 | const char *name, | ||
1726 | int *size_ret, | ||
1727 | const char *cipher_key) | ||
1728 | { | ||
1729 | Eet_File_Node *efn; | ||
1730 | char *data = NULL; | ||
1731 | unsigned long int size = 0; | ||
1732 | |||
1733 | if (size_ret) | ||
1734 | *size_ret = 0; | ||
1735 | |||
1736 | /* check to see its' an eet file pointer */ | ||
1737 | if (eet_check_pointer(ef)) | ||
1738 | return NULL; | ||
1739 | |||
1740 | if (!name) | ||
1741 | return NULL; | ||
1742 | |||
1743 | if ((ef->mode != EET_FILE_MODE_READ) && | ||
1744 | (ef->mode != EET_FILE_MODE_READ_WRITE)) | ||
1745 | return NULL; | ||
1746 | |||
1747 | /* no header, return NULL */ | ||
1748 | if (eet_check_header(ef)) | ||
1749 | return NULL; | ||
1750 | |||
1751 | LOCK_FILE(ef); | ||
1752 | |||
1753 | /* hunt hash bucket */ | ||
1754 | efn = find_node_by_name(ef, name); | ||
1755 | if (!efn) | ||
1756 | goto on_error; | ||
1757 | |||
1758 | /* get size (uncompressed, if compressed at all) */ | ||
1759 | size = efn->data_size; | ||
1760 | |||
1761 | /* allocate data */ | ||
1762 | data = malloc(size); | ||
1763 | if (!data) | ||
1764 | goto on_error; | ||
1765 | |||
1766 | /* uncompressed data */ | ||
1767 | if (efn->compression == 0) | ||
1768 | { | ||
1769 | void *data_deciphered = NULL; | ||
1770 | unsigned int data_deciphered_sz = 0; | ||
1771 | /* if we already have the data in ram... copy that */ | ||
1772 | |||
1773 | if (efn->ciphered && efn->size > size) | ||
1774 | { | ||
1775 | size = efn->size; | ||
1776 | data = realloc(data, efn->size); | ||
1777 | } | ||
1778 | |||
1779 | if (efn->data) | ||
1780 | memcpy(data, efn->data, size); | ||
1781 | else | ||
1782 | if (!read_data_from_disk(ef, efn, data, size)) | ||
1783 | goto on_error; | ||
1784 | |||
1785 | if (efn->ciphered && cipher_key) | ||
1786 | { | ||
1787 | if (eet_decipher(data, efn->size, cipher_key, strlen(cipher_key), | ||
1788 | &data_deciphered, &data_deciphered_sz)) | ||
1789 | { | ||
1790 | if (data_deciphered) | ||
1791 | free(data_deciphered); | ||
1792 | |||
1793 | goto on_error; | ||
1794 | } | ||
1795 | |||
1796 | free(data); | ||
1797 | data = data_deciphered; | ||
1798 | size = data_deciphered_sz; | ||
1799 | } | ||
1800 | } | ||
1801 | /* compressed data */ | ||
1802 | else | ||
1803 | { | ||
1804 | void *tmp_data = NULL; | ||
1805 | void *data_deciphered = NULL; | ||
1806 | unsigned int data_deciphered_sz = 0; | ||
1807 | int free_tmp = 0; | ||
1808 | int compr_size = efn->size; | ||
1809 | uLongf dlen; | ||
1810 | |||
1811 | /* if we already have the data in ram... copy that */ | ||
1812 | if (efn->data) | ||
1813 | tmp_data = efn->data; | ||
1814 | else | ||
1815 | { | ||
1816 | tmp_data = malloc(compr_size); | ||
1817 | if (!tmp_data) | ||
1818 | goto on_error; | ||
1819 | |||
1820 | free_tmp = 1; | ||
1821 | |||
1822 | if (!read_data_from_disk(ef, efn, tmp_data, compr_size)) | ||
1823 | { | ||
1824 | free(tmp_data); | ||
1825 | goto on_error; | ||
1826 | } | ||
1827 | } | ||
1828 | |||
1829 | if (efn->ciphered && cipher_key) | ||
1830 | { | ||
1831 | if (eet_decipher(tmp_data, compr_size, cipher_key, | ||
1832 | strlen(cipher_key), &data_deciphered, | ||
1833 | &data_deciphered_sz)) | ||
1834 | { | ||
1835 | if (free_tmp) | ||
1836 | free(tmp_data); | ||
1837 | |||
1838 | if (data_deciphered) | ||
1839 | free(data_deciphered); | ||
1840 | |||
1841 | goto on_error; | ||
1842 | } | ||
1843 | |||
1844 | if (free_tmp) | ||
1845 | free(tmp_data); | ||
1846 | free_tmp = 1; | ||
1847 | tmp_data = data_deciphered; | ||
1848 | compr_size = data_deciphered_sz; | ||
1849 | } | ||
1850 | |||
1851 | /* decompress it */ | ||
1852 | dlen = size; | ||
1853 | if (uncompress((Bytef *)data, &dlen, | ||
1854 | tmp_data, (uLongf)compr_size)) | ||
1855 | { | ||
1856 | if (free_tmp) | ||
1857 | free(tmp_data); | ||
1858 | goto on_error; | ||
1859 | } | ||
1860 | |||
1861 | if (free_tmp) | ||
1862 | free(tmp_data); | ||
1863 | } | ||
1864 | |||
1865 | UNLOCK_FILE(ef); | ||
1866 | |||
1867 | /* handle alias */ | ||
1868 | if (efn->alias) | ||
1869 | { | ||
1870 | void *tmp; | ||
1871 | |||
1872 | if (data[size - 1] != '\0') | ||
1873 | goto on_error; | ||
1874 | |||
1875 | tmp = eet_read_cipher(ef, data, size_ret, cipher_key); | ||
1876 | |||
1877 | free(data); | ||
1878 | |||
1879 | data = tmp; | ||
1880 | } | ||
1881 | else | ||
1882 | /* fill in return values */ | ||
1883 | if (size_ret) | ||
1884 | *size_ret = size; | ||
1885 | |||
1886 | return data; | ||
1887 | |||
1888 | on_error: | ||
1889 | UNLOCK_FILE(ef); | ||
1890 | free(data); | ||
1891 | return NULL; | ||
1892 | } /* eet_read_cipher */ | ||
1893 | |||
1894 | EAPI void * | ||
1895 | eet_read(Eet_File *ef, | ||
1896 | const char *name, | ||
1897 | int *size_ret) | ||
1898 | { | ||
1899 | return eet_read_cipher(ef, name, size_ret, NULL); | ||
1900 | } /* eet_read */ | ||
1901 | |||
1902 | EAPI const void * | ||
1903 | eet_read_direct(Eet_File *ef, | ||
1904 | const char *name, | ||
1905 | int *size_ret) | ||
1906 | { | ||
1907 | Eet_File_Node *efn; | ||
1908 | const char *data = NULL; | ||
1909 | int size = 0; | ||
1910 | |||
1911 | if (size_ret) | ||
1912 | *size_ret = 0; | ||
1913 | |||
1914 | /* check to see its' an eet file pointer */ | ||
1915 | if (eet_check_pointer(ef)) | ||
1916 | return NULL; | ||
1917 | |||
1918 | if (!name) | ||
1919 | return NULL; | ||
1920 | |||
1921 | if ((ef->mode != EET_FILE_MODE_READ) && | ||
1922 | (ef->mode != EET_FILE_MODE_READ_WRITE)) | ||
1923 | return NULL; | ||
1924 | |||
1925 | /* no header, return NULL */ | ||
1926 | if (eet_check_header(ef)) | ||
1927 | return NULL; | ||
1928 | |||
1929 | LOCK_FILE(ef); | ||
1930 | |||
1931 | /* hunt hash bucket */ | ||
1932 | efn = find_node_by_name(ef, name); | ||
1933 | if (!efn) | ||
1934 | goto on_error; | ||
1935 | |||
1936 | /* trick to detect data in memory instead of mmaped from disk */ | ||
1937 | if (efn->offset > ef->data_size && !efn->data) | ||
1938 | goto on_error; | ||
1939 | |||
1940 | /* get size (uncompressed, if compressed at all) */ | ||
1941 | size = efn->data_size; | ||
1942 | |||
1943 | if (efn->alias) | ||
1944 | { | ||
1945 | data = efn->data ? efn->data : ef->data + efn->offset; | ||
1946 | |||
1947 | /* handle alias case */ | ||
1948 | if (efn->compression) | ||
1949 | { | ||
1950 | char *tmp; | ||
1951 | int compr_size = efn->size; | ||
1952 | uLongf dlen; | ||
1953 | |||
1954 | tmp = alloca(sizeof (compr_size)); | ||
1955 | dlen = size; | ||
1956 | |||
1957 | if (uncompress((Bytef *)tmp, &dlen, (Bytef *)data, | ||
1958 | (uLongf)compr_size)) | ||
1959 | goto on_error; | ||
1960 | |||
1961 | if (tmp[compr_size - 1] != '\0') | ||
1962 | goto on_error; | ||
1963 | |||
1964 | UNLOCK_FILE(ef); | ||
1965 | |||
1966 | return eet_read_direct(ef, tmp, size_ret); | ||
1967 | } | ||
1968 | |||
1969 | if (!data) | ||
1970 | goto on_error; | ||
1971 | |||
1972 | if (data[size - 1] != '\0') | ||
1973 | goto on_error; | ||
1974 | |||
1975 | UNLOCK_FILE(ef); | ||
1976 | |||
1977 | return eet_read_direct(ef, data, size_ret); | ||
1978 | } | ||
1979 | else | ||
1980 | /* uncompressed data */ | ||
1981 | if (efn->compression == 0 | ||
1982 | && efn->ciphered == 0) | ||
1983 | data = efn->data ? efn->data : ef->data + efn->offset; /* compressed data */ | ||
1984 | else | ||
1985 | data = NULL; | ||
1986 | |||
1987 | /* fill in return values */ | ||
1988 | if (size_ret) | ||
1989 | *size_ret = size; | ||
1990 | |||
1991 | UNLOCK_FILE(ef); | ||
1992 | |||
1993 | return data; | ||
1994 | |||
1995 | on_error: | ||
1996 | UNLOCK_FILE(ef); | ||
1997 | return NULL; | ||
1998 | } /* eet_read_direct */ | ||
1999 | |||
2000 | EAPI const char * | ||
2001 | eet_alias_get(Eet_File *ef, | ||
2002 | const char *name) | ||
2003 | { | ||
2004 | Eet_File_Node *efn; | ||
2005 | const char *data = NULL; | ||
2006 | int size = 0; | ||
2007 | |||
2008 | /* check to see its' an eet file pointer */ | ||
2009 | if (eet_check_pointer(ef)) | ||
2010 | return NULL; | ||
2011 | |||
2012 | if (!name) | ||
2013 | return NULL; | ||
2014 | |||
2015 | if ((ef->mode != EET_FILE_MODE_READ) && | ||
2016 | (ef->mode != EET_FILE_MODE_READ_WRITE)) | ||
2017 | return NULL; | ||
2018 | |||
2019 | /* no header, return NULL */ | ||
2020 | if (eet_check_header(ef)) | ||
2021 | return NULL; | ||
2022 | |||
2023 | LOCK_FILE(ef); | ||
2024 | |||
2025 | /* hunt hash bucket */ | ||
2026 | efn = find_node_by_name(ef, name); | ||
2027 | if (!efn) | ||
2028 | goto on_error; | ||
2029 | |||
2030 | /* trick to detect data in memory instead of mmaped from disk */ | ||
2031 | if (efn->offset > ef->data_size && !efn->data) | ||
2032 | goto on_error; | ||
2033 | |||
2034 | /* get size (uncompressed, if compressed at all) */ | ||
2035 | size = efn->data_size; | ||
2036 | |||
2037 | if (!efn->alias) return NULL; | ||
2038 | data = efn->data ? efn->data : ef->data + efn->offset; | ||
2039 | |||
2040 | /* handle alias case */ | ||
2041 | if (efn->compression) | ||
2042 | { | ||
2043 | char *tmp; | ||
2044 | int compr_size = efn->size; | ||
2045 | uLongf dlen; | ||
2046 | |||
2047 | tmp = alloca(sizeof (compr_size)); | ||
2048 | dlen = size; | ||
2049 | |||
2050 | if (uncompress((Bytef *)tmp, &dlen, (Bytef *)data, | ||
2051 | (uLongf)compr_size)) | ||
2052 | goto on_error; | ||
2053 | |||
2054 | if (tmp[compr_size - 1] != '\0') | ||
2055 | goto on_error; | ||
2056 | |||
2057 | UNLOCK_FILE(ef); | ||
2058 | |||
2059 | return eina_stringshare_add(tmp); | ||
2060 | } | ||
2061 | |||
2062 | if (!data) | ||
2063 | goto on_error; | ||
2064 | |||
2065 | if (data[size - 1] != '\0') | ||
2066 | goto on_error; | ||
2067 | |||
2068 | UNLOCK_FILE(ef); | ||
2069 | |||
2070 | return eina_stringshare_add(data); | ||
2071 | |||
2072 | on_error: | ||
2073 | UNLOCK_FILE(ef); | ||
2074 | return NULL; | ||
2075 | } | ||
2076 | |||
2077 | EAPI Eina_Bool | ||
2078 | eet_alias(Eet_File *ef, | ||
2079 | const char *name, | ||
2080 | const char *destination, | ||
2081 | int comp) | ||
2082 | { | ||
2083 | Eet_File_Node *efn; | ||
2084 | void *data2; | ||
2085 | Eina_Bool exists_already = EINA_FALSE; | ||
2086 | int data_size; | ||
2087 | int hash; | ||
2088 | |||
2089 | /* check to see its' an eet file pointer */ | ||
2090 | if (eet_check_pointer(ef)) | ||
2091 | return EINA_FALSE; | ||
2092 | |||
2093 | if ((!name) || (!destination)) | ||
2094 | return EINA_FALSE; | ||
2095 | |||
2096 | if ((ef->mode != EET_FILE_MODE_WRITE) && | ||
2097 | (ef->mode != EET_FILE_MODE_READ_WRITE)) | ||
2098 | return EINA_FALSE; | ||
2099 | |||
2100 | LOCK_FILE(ef); | ||
2101 | |||
2102 | if (!ef->header) | ||
2103 | { | ||
2104 | /* allocate header */ | ||
2105 | ef->header = calloc(1, sizeof(Eet_File_Header)); | ||
2106 | if (!ef->header) | ||
2107 | goto on_error; | ||
2108 | |||
2109 | ef->header->magic = EET_MAGIC_FILE_HEADER; | ||
2110 | /* allocate directory block in ram */ | ||
2111 | ef->header->directory = calloc(1, sizeof(Eet_File_Directory)); | ||
2112 | if (!ef->header->directory) | ||
2113 | { | ||
2114 | free(ef->header); | ||
2115 | ef->header = NULL; | ||
2116 | goto on_error; | ||
2117 | } | ||
2118 | |||
2119 | /* 8 bit hash table (256 buckets) */ | ||
2120 | ef->header->directory->size = 8; | ||
2121 | /* allocate base hash table */ | ||
2122 | ef->header->directory->nodes = | ||
2123 | calloc(1, sizeof(Eet_File_Node *) * | ||
2124 | (1 << ef->header->directory->size)); | ||
2125 | if (!ef->header->directory->nodes) | ||
2126 | { | ||
2127 | free(ef->header->directory); | ||
2128 | ef->header = NULL; | ||
2129 | goto on_error; | ||
2130 | } | ||
2131 | } | ||
2132 | |||
2133 | /* figure hash bucket */ | ||
2134 | hash = _eet_hash_gen(name, ef->header->directory->size); | ||
2135 | |||
2136 | data_size = comp ? | ||
2137 | 12 + (((strlen(destination) + 1) * 101) / 100) | ||
2138 | : strlen(destination) + 1; | ||
2139 | |||
2140 | data2 = malloc(data_size); | ||
2141 | if (!data2) | ||
2142 | goto on_error; | ||
2143 | |||
2144 | /* if we want to compress */ | ||
2145 | if (comp) | ||
2146 | { | ||
2147 | uLongf buflen; | ||
2148 | |||
2149 | /* compress the data with max compression */ | ||
2150 | buflen = (uLongf)data_size; | ||
2151 | if (compress2((Bytef *)data2, &buflen, (Bytef *)destination, | ||
2152 | (uLong)strlen(destination) + 1, | ||
2153 | Z_BEST_COMPRESSION) != Z_OK) | ||
2154 | { | ||
2155 | free(data2); | ||
2156 | goto on_error; | ||
2157 | } | ||
2158 | |||
2159 | /* record compressed chunk size */ | ||
2160 | data_size = (int)buflen; | ||
2161 | if (data_size < 0 || data_size >= (int)(strlen(destination) + 1)) | ||
2162 | { | ||
2163 | comp = 0; | ||
2164 | data_size = strlen(destination) + 1; | ||
2165 | } | ||
2166 | else | ||
2167 | { | ||
2168 | void *data3; | ||
2169 | |||
2170 | data3 = realloc(data2, data_size); | ||
2171 | if (data3) | ||
2172 | data2 = data3; | ||
2173 | } | ||
2174 | } | ||
2175 | |||
2176 | if (!comp) | ||
2177 | memcpy(data2, destination, data_size); | ||
2178 | |||
2179 | /* Does this node already exist? */ | ||
2180 | for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next) | ||
2181 | { | ||
2182 | /* if it matches */ | ||
2183 | if ((efn->name) && (eet_string_match(efn->name, name))) | ||
2184 | { | ||
2185 | free(efn->data); | ||
2186 | efn->alias = 1; | ||
2187 | efn->ciphered = 0; | ||
2188 | efn->compression = !!comp; | ||
2189 | efn->size = data_size; | ||
2190 | efn->data_size = strlen(destination) + 1; | ||
2191 | efn->data = data2; | ||
2192 | /* Put the offset above the limit to avoid direct access */ | ||
2193 | efn->offset = ef->data_size + 1; | ||
2194 | exists_already = EINA_TRUE; | ||
2195 | |||
2196 | break; | ||
2197 | } | ||
2198 | } | ||
2199 | if (!exists_already) | ||
2200 | { | ||
2201 | efn = malloc(sizeof(Eet_File_Node)); | ||
2202 | if (!efn) | ||
2203 | { | ||
2204 | free(data2); | ||
2205 | goto on_error; | ||
2206 | } | ||
2207 | |||
2208 | efn->name = strdup(name); | ||
2209 | efn->name_size = strlen(efn->name) + 1; | ||
2210 | efn->free_name = 1; | ||
2211 | |||
2212 | efn->next = ef->header->directory->nodes[hash]; | ||
2213 | ef->header->directory->nodes[hash] = efn; | ||
2214 | /* Put the offset above the limit to avoid direct access */ | ||
2215 | efn->offset = ef->data_size + 1; | ||
2216 | efn->alias = 1; | ||
2217 | efn->ciphered = 0; | ||
2218 | efn->compression = !!comp; | ||
2219 | efn->size = data_size; | ||
2220 | efn->data_size = strlen(destination) + 1; | ||
2221 | efn->data = data2; | ||
2222 | } | ||
2223 | |||
2224 | /* flags that writes are pending */ | ||
2225 | ef->writes_pending = 1; | ||
2226 | |||
2227 | UNLOCK_FILE(ef); | ||
2228 | return EINA_TRUE; | ||
2229 | |||
2230 | on_error: | ||
2231 | UNLOCK_FILE(ef); | ||
2232 | return EINA_FALSE; | ||
2233 | } /* eet_alias */ | ||
2234 | |||
2235 | EAPI int | ||
2236 | eet_write_cipher(Eet_File *ef, | ||
2237 | const char *name, | ||
2238 | const void *data, | ||
2239 | int size, | ||
2240 | int comp, | ||
2241 | const char *cipher_key) | ||
2242 | { | ||
2243 | Eet_File_Node *efn; | ||
2244 | void *data2 = NULL; | ||
2245 | int exists_already = 0; | ||
2246 | int data_size; | ||
2247 | int hash; | ||
2248 | |||
2249 | /* check to see its' an eet file pointer */ | ||
2250 | if (eet_check_pointer(ef)) | ||
2251 | return 0; | ||
2252 | |||
2253 | if ((!name) || (!data) || (size <= 0)) | ||
2254 | return 0; | ||
2255 | |||
2256 | if ((ef->mode != EET_FILE_MODE_WRITE) && | ||
2257 | (ef->mode != EET_FILE_MODE_READ_WRITE)) | ||
2258 | return 0; | ||
2259 | |||
2260 | LOCK_FILE(ef); | ||
2261 | |||
2262 | if (!ef->header) | ||
2263 | { | ||
2264 | /* allocate header */ | ||
2265 | ef->header = calloc(1, sizeof(Eet_File_Header)); | ||
2266 | if (!ef->header) | ||
2267 | goto on_error; | ||
2268 | |||
2269 | ef->header->magic = EET_MAGIC_FILE_HEADER; | ||
2270 | /* allocate directory block in ram */ | ||
2271 | ef->header->directory = calloc(1, sizeof(Eet_File_Directory)); | ||
2272 | if (!ef->header->directory) | ||
2273 | { | ||
2274 | free(ef->header); | ||
2275 | ef->header = NULL; | ||
2276 | goto on_error; | ||
2277 | } | ||
2278 | |||
2279 | /* 8 bit hash table (256 buckets) */ | ||
2280 | ef->header->directory->size = 8; | ||
2281 | /* allocate base hash table */ | ||
2282 | ef->header->directory->nodes = | ||
2283 | calloc(1, sizeof(Eet_File_Node *) * | ||
2284 | (1 << ef->header->directory->size)); | ||
2285 | if (!ef->header->directory->nodes) | ||
2286 | { | ||
2287 | free(ef->header->directory); | ||
2288 | ef->header = NULL; | ||
2289 | goto on_error; | ||
2290 | } | ||
2291 | } | ||
2292 | |||
2293 | /* figure hash bucket */ | ||
2294 | hash = _eet_hash_gen(name, ef->header->directory->size); | ||
2295 | |||
2296 | data_size = comp ? 12 + ((size * 101) / 100) : size; | ||
2297 | |||
2298 | if (comp || !cipher_key) | ||
2299 | { | ||
2300 | data2 = malloc(data_size); | ||
2301 | if (!data2) | ||
2302 | goto on_error; | ||
2303 | } | ||
2304 | |||
2305 | /* if we want to compress */ | ||
2306 | if (comp) | ||
2307 | { | ||
2308 | uLongf buflen; | ||
2309 | |||
2310 | /* compress the data with max compression */ | ||
2311 | buflen = (uLongf)data_size; | ||
2312 | if (compress2((Bytef *)data2, &buflen, (Bytef *)data, | ||
2313 | (uLong)size, Z_BEST_COMPRESSION) != Z_OK) | ||
2314 | { | ||
2315 | free(data2); | ||
2316 | goto on_error; | ||
2317 | } | ||
2318 | |||
2319 | /* record compressed chunk size */ | ||
2320 | data_size = (int)buflen; | ||
2321 | if (data_size < 0 || data_size >= size) | ||
2322 | { | ||
2323 | comp = 0; | ||
2324 | data_size = size; | ||
2325 | } | ||
2326 | else | ||
2327 | { | ||
2328 | void *data3; | ||
2329 | |||
2330 | data3 = realloc(data2, data_size); | ||
2331 | if (data3) | ||
2332 | data2 = data3; | ||
2333 | } | ||
2334 | } | ||
2335 | |||
2336 | if (cipher_key) | ||
2337 | { | ||
2338 | void *data_ciphered = NULL; | ||
2339 | unsigned int data_ciphered_sz = 0; | ||
2340 | const void *tmp; | ||
2341 | |||
2342 | tmp = comp ? data2 : data; | ||
2343 | if (!eet_cipher(tmp, data_size, cipher_key, strlen(cipher_key), | ||
2344 | &data_ciphered, &data_ciphered_sz)) | ||
2345 | { | ||
2346 | if (data2) | ||
2347 | free(data2); | ||
2348 | |||
2349 | data2 = data_ciphered; | ||
2350 | data_size = data_ciphered_sz; | ||
2351 | } | ||
2352 | else | ||
2353 | { | ||
2354 | if (data_ciphered) | ||
2355 | free(data_ciphered); | ||
2356 | |||
2357 | cipher_key = NULL; | ||
2358 | } | ||
2359 | } | ||
2360 | else | ||
2361 | if (!comp) | ||
2362 | memcpy(data2, data, size); | ||
2363 | |||
2364 | /* Does this node already exist? */ | ||
2365 | for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next) | ||
2366 | { | ||
2367 | /* if it matches */ | ||
2368 | if ((efn->name) && (eet_string_match(efn->name, name))) | ||
2369 | { | ||
2370 | free(efn->data); | ||
2371 | efn->alias = 0; | ||
2372 | efn->ciphered = cipher_key ? 1 : 0; | ||
2373 | efn->compression = !!comp; | ||
2374 | efn->size = data_size; | ||
2375 | efn->data_size = size; | ||
2376 | efn->data = data2; | ||
2377 | /* Put the offset above the limit to avoid direct access */ | ||
2378 | efn->offset = ef->data_size + 1; | ||
2379 | exists_already = 1; | ||
2380 | break; | ||
2381 | } | ||
2382 | } | ||
2383 | if (!exists_already) | ||
2384 | { | ||
2385 | efn = malloc(sizeof(Eet_File_Node)); | ||
2386 | if (!efn) | ||
2387 | { | ||
2388 | free(data2); | ||
2389 | goto on_error; | ||
2390 | } | ||
2391 | |||
2392 | efn->name = strdup(name); | ||
2393 | efn->name_size = strlen(efn->name) + 1; | ||
2394 | efn->free_name = 1; | ||
2395 | |||
2396 | efn->next = ef->header->directory->nodes[hash]; | ||
2397 | ef->header->directory->nodes[hash] = efn; | ||
2398 | /* Put the offset above the limit to avoid direct access */ | ||
2399 | efn->offset = ef->data_size + 1; | ||
2400 | efn->alias = 0; | ||
2401 | efn->ciphered = cipher_key ? 1 : 0; | ||
2402 | efn->compression = !!comp; | ||
2403 | efn->size = data_size; | ||
2404 | efn->data_size = size; | ||
2405 | efn->data = data2; | ||
2406 | } | ||
2407 | |||
2408 | /* flags that writes are pending */ | ||
2409 | ef->writes_pending = 1; | ||
2410 | UNLOCK_FILE(ef); | ||
2411 | return data_size; | ||
2412 | |||
2413 | on_error: | ||
2414 | UNLOCK_FILE(ef); | ||
2415 | return 0; | ||
2416 | } /* eet_write_cipher */ | ||
2417 | |||
2418 | EAPI int | ||
2419 | eet_write(Eet_File *ef, | ||
2420 | const char *name, | ||
2421 | const void *data, | ||
2422 | int size, | ||
2423 | int comp) | ||
2424 | { | ||
2425 | return eet_write_cipher(ef, name, data, size, comp, NULL); | ||
2426 | } /* eet_write */ | ||
2427 | |||
2428 | EAPI int | ||
2429 | eet_delete(Eet_File *ef, | ||
2430 | const char *name) | ||
2431 | { | ||
2432 | Eet_File_Node *efn; | ||
2433 | Eet_File_Node *pefn; | ||
2434 | int hash; | ||
2435 | int exists_already = 0; | ||
2436 | |||
2437 | /* check to see its' an eet file pointer */ | ||
2438 | if (eet_check_pointer(ef)) | ||
2439 | return 0; | ||
2440 | |||
2441 | if (!name) | ||
2442 | return 0; | ||
2443 | |||
2444 | /* deleting keys is only possible in RW or WRITE mode */ | ||
2445 | if (ef->mode == EET_FILE_MODE_READ) | ||
2446 | return 0; | ||
2447 | |||
2448 | if (eet_check_header(ef)) | ||
2449 | return 0; | ||
2450 | |||
2451 | LOCK_FILE(ef); | ||
2452 | |||
2453 | /* figure hash bucket */ | ||
2454 | hash = _eet_hash_gen(name, ef->header->directory->size); | ||
2455 | |||
2456 | /* Does this node already exist? */ | ||
2457 | for (pefn = NULL, efn = ef->header->directory->nodes[hash]; | ||
2458 | efn; | ||
2459 | pefn = efn, efn = efn->next) | ||
2460 | { | ||
2461 | /* if it matches */ | ||
2462 | if (eet_string_match(efn->name, name)) | ||
2463 | { | ||
2464 | if (efn->data) | ||
2465 | free(efn->data); | ||
2466 | |||
2467 | if (!pefn) | ||
2468 | ef->header->directory->nodes[hash] = efn->next; | ||
2469 | else | ||
2470 | pefn->next = efn->next; | ||
2471 | |||
2472 | if (efn->free_name) | ||
2473 | free(efn->name); | ||
2474 | |||
2475 | free(efn); | ||
2476 | exists_already = 1; | ||
2477 | break; | ||
2478 | } | ||
2479 | } | ||
2480 | /* flags that writes are pending */ | ||
2481 | if (exists_already) | ||
2482 | ef->writes_pending = 1; | ||
2483 | |||
2484 | UNLOCK_FILE(ef); | ||
2485 | |||
2486 | /* update access time */ | ||
2487 | return exists_already; | ||
2488 | } /* eet_delete */ | ||
2489 | |||
2490 | EAPI Eet_Dictionary * | ||
2491 | eet_dictionary_get(Eet_File *ef) | ||
2492 | { | ||
2493 | if (eet_check_pointer(ef)) | ||
2494 | return NULL; | ||
2495 | |||
2496 | return ef->ed; | ||
2497 | } /* eet_dictionary_get */ | ||
2498 | |||
2499 | EAPI char ** | ||
2500 | eet_list(Eet_File *ef, | ||
2501 | const char *glob, | ||
2502 | int *count_ret) | ||
2503 | { | ||
2504 | Eet_File_Node *efn; | ||
2505 | char **list_ret = NULL; | ||
2506 | int list_count = 0; | ||
2507 | int list_count_alloc = 0; | ||
2508 | int i, num; | ||
2509 | |||
2510 | /* check to see its' an eet file pointer */ | ||
2511 | if (eet_check_pointer(ef) || eet_check_header(ef) || | ||
2512 | (!glob) || | ||
2513 | ((ef->mode != EET_FILE_MODE_READ) && | ||
2514 | (ef->mode != EET_FILE_MODE_READ_WRITE))) | ||
2515 | { | ||
2516 | if (count_ret) | ||
2517 | *count_ret = 0; | ||
2518 | |||
2519 | return NULL; | ||
2520 | } | ||
2521 | |||
2522 | if (!strcmp(glob, "*")) | ||
2523 | glob = NULL; | ||
2524 | |||
2525 | LOCK_FILE(ef); | ||
2526 | |||
2527 | /* loop through all entries */ | ||
2528 | num = (1 << ef->header->directory->size); | ||
2529 | for (i = 0; i < num; i++) | ||
2530 | { | ||
2531 | for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) | ||
2532 | { | ||
2533 | /* if the entry matches the input glob | ||
2534 | * check for * explicitly, because on some systems, * isn't well | ||
2535 | * supported | ||
2536 | */ | ||
2537 | if ((!glob) || !fnmatch(glob, efn->name, 0)) | ||
2538 | { | ||
2539 | /* add it to our list */ | ||
2540 | list_count++; | ||
2541 | |||
2542 | /* only realloc in 32 entry chunks */ | ||
2543 | if (list_count > list_count_alloc) | ||
2544 | { | ||
2545 | char **new_list = NULL; | ||
2546 | |||
2547 | list_count_alloc += 64; | ||
2548 | new_list = | ||
2549 | realloc(list_ret, list_count_alloc * (sizeof(char *))); | ||
2550 | if (!new_list) | ||
2551 | { | ||
2552 | free(list_ret); | ||
2553 | |||
2554 | goto on_error; | ||
2555 | } | ||
2556 | |||
2557 | list_ret = new_list; | ||
2558 | } | ||
2559 | |||
2560 | /* put pointer of name string in */ | ||
2561 | list_ret[list_count - 1] = efn->name; | ||
2562 | } | ||
2563 | } | ||
2564 | } | ||
2565 | |||
2566 | UNLOCK_FILE(ef); | ||
2567 | |||
2568 | /* return count and list */ | ||
2569 | if (count_ret) | ||
2570 | *count_ret = list_count; | ||
2571 | |||
2572 | return list_ret; | ||
2573 | |||
2574 | on_error: | ||
2575 | UNLOCK_FILE(ef); | ||
2576 | |||
2577 | if (count_ret) | ||
2578 | *count_ret = 0; | ||
2579 | |||
2580 | return NULL; | ||
2581 | } /* eet_list */ | ||
2582 | |||
2583 | EAPI int | ||
2584 | eet_num_entries(Eet_File *ef) | ||
2585 | { | ||
2586 | int i, num, ret = 0; | ||
2587 | Eet_File_Node *efn; | ||
2588 | |||
2589 | /* check to see its' an eet file pointer */ | ||
2590 | if (eet_check_pointer(ef) || eet_check_header(ef) || | ||
2591 | ((ef->mode != EET_FILE_MODE_READ) && | ||
2592 | (ef->mode != EET_FILE_MODE_READ_WRITE))) | ||
2593 | return -1; | ||
2594 | |||
2595 | LOCK_FILE(ef); | ||
2596 | |||
2597 | /* loop through all entries */ | ||
2598 | num = (1 << ef->header->directory->size); | ||
2599 | for (i = 0; i < num; i++) | ||
2600 | { | ||
2601 | for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) | ||
2602 | ret++; | ||
2603 | } | ||
2604 | |||
2605 | UNLOCK_FILE(ef); | ||
2606 | |||
2607 | return ret; | ||
2608 | } /* eet_num_entries */ | ||
2609 | |||
2610 | static Eet_File_Node * | ||
2611 | find_node_by_name(Eet_File *ef, | ||
2612 | const char *name) | ||
2613 | { | ||
2614 | Eet_File_Node *efn; | ||
2615 | int hash; | ||
2616 | |||
2617 | /* get hash bucket this should be in */ | ||
2618 | hash = _eet_hash_gen(name, ef->header->directory->size); | ||
2619 | |||
2620 | for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next) | ||
2621 | { | ||
2622 | if (eet_string_match(efn->name, name)) | ||
2623 | return efn; | ||
2624 | } | ||
2625 | |||
2626 | return NULL; | ||
2627 | } /* find_node_by_name */ | ||
2628 | |||
2629 | static int | ||
2630 | read_data_from_disk(Eet_File *ef, | ||
2631 | Eet_File_Node *efn, | ||
2632 | void *buf, | ||
2633 | int len) | ||
2634 | { | ||
2635 | if (efn->offset > ef->data_size) | ||
2636 | return 0; | ||
2637 | |||
2638 | if (!ef->data) | ||
2639 | return 0; | ||
2640 | |||
2641 | if ((efn->offset + len) > ef->data_size) | ||
2642 | return 0; | ||
2643 | |||
2644 | memcpy(buf, ef->data + efn->offset, len); | ||
2645 | |||
2646 | return len; | ||
2647 | } /* read_data_from_disk */ | ||
2648 | |||
diff --git a/libraries/eet/src/lib/eet_node.c b/libraries/eet/src/lib/eet_node.c new file mode 100644 index 0000000..d90ef83 --- /dev/null +++ b/libraries/eet/src/lib/eet_node.c | |||
@@ -0,0 +1,797 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif /* ifdef HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <string.h> | ||
6 | #include <stdio.h> | ||
7 | |||
8 | #ifdef HAVE_EVIL | ||
9 | # include <Evil.h> | ||
10 | #endif /* ifdef HAVE_EVIL */ | ||
11 | |||
12 | #include <Eina.h> | ||
13 | |||
14 | #include "Eet.h" | ||
15 | #include "Eet_private.h" | ||
16 | |||
17 | static Eina_Mempool *_eet_node_mp = NULL; | ||
18 | |||
19 | Eet_Node * | ||
20 | eet_node_new(void) | ||
21 | { | ||
22 | Eet_Node *result; | ||
23 | |||
24 | result = eina_mempool_malloc(_eet_node_mp, sizeof (Eet_Node)); | ||
25 | if (!result) | ||
26 | return NULL; | ||
27 | |||
28 | memset(result, 0, sizeof (Eet_Node)); | ||
29 | return result; | ||
30 | } /* eet_node_new */ | ||
31 | |||
32 | void | ||
33 | eet_node_free(Eet_Node *node) | ||
34 | { | ||
35 | eina_mempool_free(_eet_node_mp, node); | ||
36 | } /* eet_node_free */ | ||
37 | |||
38 | static Eet_Node * | ||
39 | _eet_node_new(const char *name, | ||
40 | int type) | ||
41 | { | ||
42 | Eet_Node *n; | ||
43 | |||
44 | n = eet_node_new(); | ||
45 | if (!n) | ||
46 | return NULL; | ||
47 | |||
48 | n->type = type; | ||
49 | n->name = eina_stringshare_add(name); | ||
50 | |||
51 | return n; | ||
52 | } /* _eet_node_new */ | ||
53 | |||
54 | static void | ||
55 | _eet_node_append(Eet_Node *n, | ||
56 | Eina_List *nodes) | ||
57 | { | ||
58 | Eet_Node *value; | ||
59 | Eina_List *l; | ||
60 | |||
61 | EINA_LIST_REVERSE_FOREACH(nodes, l, value) | ||
62 | { | ||
63 | value->next = n->values; | ||
64 | n->values = value; | ||
65 | } | ||
66 | } /* _eet_node_append */ | ||
67 | |||
68 | #define EET_NODE_NEW(Eet_type, Name, Value, Type) \ | ||
69 | EAPI Eet_Node * \ | ||
70 | eet_node_ ## Name ## _new(const char *name, Type Value) \ | ||
71 | { \ | ||
72 | Eet_Node *n; \ | ||
73 | \ | ||
74 | n = _eet_node_new(name, Eet_type); \ | ||
75 | if (!n) { return NULL; } \ | ||
76 | \ | ||
77 | n->data.value.Value = Value; \ | ||
78 | \ | ||
79 | return n; \ | ||
80 | } | ||
81 | |||
82 | #define EET_NODE_STR_NEW(Eet_type, Name, Value, Type) \ | ||
83 | EAPI Eet_Node * \ | ||
84 | eet_node_ ## Name ## _new(const char *name, Type Value) \ | ||
85 | { \ | ||
86 | Eet_Node *n; \ | ||
87 | \ | ||
88 | n = _eet_node_new(name, Eet_type); \ | ||
89 | if (!n) { return NULL; } \ | ||
90 | \ | ||
91 | n->data.value.Value = eina_stringshare_add(Value); \ | ||
92 | \ | ||
93 | return n; \ | ||
94 | } | ||
95 | |||
96 | EET_NODE_NEW(EET_T_CHAR, char, c, char) | ||
97 | EET_NODE_NEW(EET_T_SHORT, short, s, short) | ||
98 | EET_NODE_NEW(EET_T_INT, int, i, int) | ||
99 | EET_NODE_NEW(EET_T_LONG_LONG, long_long, l, long long) | ||
100 | EET_NODE_NEW(EET_T_FLOAT, float, f, float) | ||
101 | EET_NODE_NEW(EET_T_DOUBLE, double, d, double) | ||
102 | EET_NODE_NEW(EET_T_UCHAR, unsigned_char, uc, unsigned char) | ||
103 | EET_NODE_NEW(EET_T_USHORT, unsigned_short, us, unsigned short) | ||
104 | EET_NODE_NEW(EET_T_UINT, unsigned_int, ui, unsigned int) | ||
105 | EET_NODE_NEW(EET_T_ULONG_LONG, unsigned_long_long, ul, unsigned long long) | ||
106 | EET_NODE_STR_NEW(EET_T_STRING, string, str, const char *) | ||
107 | EET_NODE_STR_NEW(EET_T_INLINED_STRING, inlined_string, str, const char *) | ||
108 | |||
109 | Eet_Node * | ||
110 | eet_node_null_new(const char *name) | ||
111 | { | ||
112 | Eet_Node *n; | ||
113 | |||
114 | n = _eet_node_new(name, EET_T_NULL); | ||
115 | if (!n) | ||
116 | return NULL; | ||
117 | |||
118 | n->data.value.str = NULL; | ||
119 | |||
120 | return n; | ||
121 | } | ||
122 | |||
123 | Eet_Node * | ||
124 | eet_node_list_new(const char *name, | ||
125 | Eina_List *nodes) | ||
126 | { | ||
127 | Eet_Node *n; | ||
128 | |||
129 | n = _eet_node_new(name, EET_G_LIST); | ||
130 | if (!n) | ||
131 | return NULL; | ||
132 | |||
133 | _eet_node_append(n, nodes); | ||
134 | |||
135 | return n; | ||
136 | } /* eet_node_list_new */ | ||
137 | |||
138 | Eet_Node * | ||
139 | eet_node_array_new(const char *name, | ||
140 | int count, | ||
141 | Eina_List *nodes) | ||
142 | { | ||
143 | Eet_Node *n; | ||
144 | |||
145 | n = _eet_node_new(name, EET_G_ARRAY); | ||
146 | if (!n) | ||
147 | return NULL; | ||
148 | |||
149 | n->count = count; | ||
150 | |||
151 | _eet_node_append(n, nodes); | ||
152 | |||
153 | return n; | ||
154 | } /* eet_node_array_new */ | ||
155 | |||
156 | Eet_Node * | ||
157 | eet_node_var_array_new(const char *name, | ||
158 | Eina_List *nodes) | ||
159 | { | ||
160 | Eet_Node *n; | ||
161 | |||
162 | n = _eet_node_new(name, EET_G_VAR_ARRAY); | ||
163 | if (!n) | ||
164 | return NULL; | ||
165 | |||
166 | n->count = eina_list_count(nodes); | ||
167 | |||
168 | _eet_node_append(n, nodes); | ||
169 | |||
170 | return n; | ||
171 | } /* eet_node_var_array_new */ | ||
172 | |||
173 | Eet_Node * | ||
174 | eet_node_hash_new(const char *name, | ||
175 | const char *key, | ||
176 | Eet_Node *node) | ||
177 | { | ||
178 | Eina_List *nodes; | ||
179 | Eet_Node *n; | ||
180 | |||
181 | if (!node) | ||
182 | return NULL; | ||
183 | |||
184 | n = _eet_node_new(name, EET_G_HASH); | ||
185 | if (!n) | ||
186 | return NULL; | ||
187 | |||
188 | n->key = eina_stringshare_add(key); | ||
189 | nodes = eina_list_append(NULL, node); | ||
190 | |||
191 | _eet_node_append(n, nodes); | ||
192 | |||
193 | return n; | ||
194 | } /* eet_node_hash_new */ | ||
195 | |||
196 | Eet_Node * | ||
197 | eet_node_struct_new(const char *name, | ||
198 | Eina_List *nodes) | ||
199 | { | ||
200 | Eet_Node *n; | ||
201 | |||
202 | n = _eet_node_new(name, EET_G_UNKNOWN); | ||
203 | if (!n) | ||
204 | return NULL; | ||
205 | |||
206 | _eet_node_append(n, nodes); | ||
207 | |||
208 | return n; | ||
209 | } /* eet_node_struct_new */ | ||
210 | |||
211 | Eet_Node * | ||
212 | eet_node_struct_child_new(const char *parent, | ||
213 | Eet_Node *child) | ||
214 | { | ||
215 | Eet_Node *n; | ||
216 | |||
217 | if (!child) return NULL; | ||
218 | |||
219 | if (child->type != EET_G_UNKNOWN) | ||
220 | return child; | ||
221 | |||
222 | n = _eet_node_new(parent, EET_G_UNKNOWN); | ||
223 | if (!n) | ||
224 | return NULL; | ||
225 | |||
226 | _eet_node_append(n, eina_list_prepend(NULL, child)); | ||
227 | |||
228 | return n; | ||
229 | } /* eet_node_struct_child_new */ | ||
230 | |||
231 | Eet_Node * | ||
232 | eet_node_children_get(Eet_Node *node) | ||
233 | { | ||
234 | if (!node) return NULL; | ||
235 | return node->values; | ||
236 | } | ||
237 | |||
238 | Eet_Node * | ||
239 | eet_node_next_get(Eet_Node *node) | ||
240 | { | ||
241 | if (!node) return NULL; | ||
242 | return node->next; | ||
243 | } | ||
244 | |||
245 | Eet_Node * | ||
246 | eet_node_parent_get(Eet_Node *node) | ||
247 | { | ||
248 | if (!node) return NULL; | ||
249 | return node->parent; | ||
250 | } | ||
251 | |||
252 | void | ||
253 | eet_node_list_append(Eet_Node *parent, | ||
254 | const char *name, | ||
255 | Eet_Node *child) | ||
256 | { | ||
257 | const char *tmp; | ||
258 | Eet_Node *nn; | ||
259 | |||
260 | if ((!parent) || (!child)) return; | ||
261 | tmp = eina_stringshare_add(name); | ||
262 | |||
263 | for (nn = parent->values; nn; nn = nn->next) | ||
264 | if (nn->name == tmp && nn->type == EET_G_LIST) | ||
265 | { | ||
266 | Eet_Node *n; | ||
267 | |||
268 | if (!nn->values) | ||
269 | nn->values = child; | ||
270 | else | ||
271 | { | ||
272 | for (n = nn->values; n->next; n = n->next) | ||
273 | ; | ||
274 | n->next = child; | ||
275 | } | ||
276 | |||
277 | child->next = NULL; | ||
278 | |||
279 | eina_stringshare_del(tmp); | ||
280 | |||
281 | return; | ||
282 | } | ||
283 | |||
284 | /* No list found, so create it. */ | ||
285 | nn = eet_node_list_new(tmp, eina_list_append(NULL, child)); | ||
286 | |||
287 | /* And add it to the parent. */ | ||
288 | nn->next = parent->values; | ||
289 | parent->values = nn; | ||
290 | |||
291 | eina_stringshare_del(tmp); | ||
292 | } /* eet_node_list_append */ | ||
293 | |||
294 | void | ||
295 | eet_node_struct_append(Eet_Node *parent, | ||
296 | const char *name, | ||
297 | Eet_Node *child) | ||
298 | { | ||
299 | const char *tmp; | ||
300 | Eet_Node *prev; | ||
301 | Eet_Node *nn; | ||
302 | |||
303 | if ((!parent) || (!child)) return; | ||
304 | if (parent->type != EET_G_UNKNOWN) | ||
305 | { | ||
306 | ERR("[%s] is not a structure. Will not insert [%s] in it", | ||
307 | parent->name, | ||
308 | name); | ||
309 | eet_node_del(child); | ||
310 | return; | ||
311 | } | ||
312 | |||
313 | tmp = eina_stringshare_add(name); | ||
314 | |||
315 | for (prev = NULL, nn = parent->values; nn; prev = nn, nn = nn->next) | ||
316 | if (nn->name == tmp && nn->type == child->type) | ||
317 | { | ||
318 | if (prev) | ||
319 | prev->next = nn->next; | ||
320 | else | ||
321 | parent->values = nn->next; | ||
322 | |||
323 | nn->next = NULL; | ||
324 | eet_node_del(nn); | ||
325 | |||
326 | break; | ||
327 | } | ||
328 | |||
329 | if (prev) | ||
330 | { | ||
331 | prev->next = child; | ||
332 | child->next = NULL; | ||
333 | } | ||
334 | else | ||
335 | { | ||
336 | child->next = NULL; | ||
337 | parent->values = child; | ||
338 | } | ||
339 | |||
340 | eina_stringshare_del(tmp); | ||
341 | } /* eet_node_struct_append */ | ||
342 | |||
343 | void | ||
344 | eet_node_hash_add(Eet_Node *parent, | ||
345 | const char *name, | ||
346 | const char *key, | ||
347 | Eet_Node *child) | ||
348 | { | ||
349 | Eet_Node *nn; | ||
350 | |||
351 | if ((!parent) || (!child)) return; | ||
352 | |||
353 | /* No list found, so create it. */ | ||
354 | nn = eet_node_hash_new(name, key, child); | ||
355 | |||
356 | /* And add it to the parent. */ | ||
357 | nn->next = parent->values; | ||
358 | parent->values = nn; | ||
359 | } /* eet_node_hash_add */ | ||
360 | |||
361 | int | ||
362 | eet_node_type_get(Eet_Node *node) | ||
363 | { | ||
364 | if (!node) return EET_T_UNKNOW; | ||
365 | return node->type; | ||
366 | } | ||
367 | |||
368 | Eet_Node_Data * | ||
369 | eet_node_value_get(Eet_Node *node) | ||
370 | { | ||
371 | if (!node) return NULL; | ||
372 | return &node->data; | ||
373 | } | ||
374 | |||
375 | const char * | ||
376 | eet_node_name_get(Eet_Node *node) | ||
377 | { | ||
378 | if (!node) return NULL; | ||
379 | return node->name; | ||
380 | } | ||
381 | |||
382 | void | ||
383 | eet_node_del(Eet_Node *n) | ||
384 | { | ||
385 | Eet_Node *nn; | ||
386 | Eet_Node *tmp; | ||
387 | |||
388 | if (!n) | ||
389 | return; | ||
390 | |||
391 | switch (n->type) | ||
392 | { | ||
393 | case EET_G_HASH: | ||
394 | eina_stringshare_del(n->key); | ||
395 | |||
396 | case EET_G_UNKNOWN: | ||
397 | case EET_G_VAR_ARRAY: | ||
398 | case EET_G_ARRAY: | ||
399 | case EET_G_LIST: | ||
400 | for (nn = n->values; nn; ) | ||
401 | { | ||
402 | tmp = nn; | ||
403 | nn = nn->next; | ||
404 | eet_node_del(tmp); | ||
405 | } | ||
406 | break; | ||
407 | |||
408 | case EET_T_STRING: | ||
409 | case EET_T_INLINED_STRING: | ||
410 | eina_stringshare_del(n->data.value.str); | ||
411 | break; | ||
412 | |||
413 | case EET_T_CHAR: | ||
414 | case EET_T_SHORT: | ||
415 | case EET_T_INT: | ||
416 | case EET_T_LONG_LONG: | ||
417 | case EET_T_FLOAT: | ||
418 | case EET_T_DOUBLE: | ||
419 | case EET_T_UCHAR: | ||
420 | case EET_T_USHORT: | ||
421 | case EET_T_UINT: | ||
422 | break; | ||
423 | } /* switch */ | ||
424 | |||
425 | eina_stringshare_del(n->name); | ||
426 | eet_node_free(n); | ||
427 | } /* eet_node_del */ | ||
428 | |||
429 | static const char *eet_node_dump_g_name[6] = { | ||
430 | "struct", | ||
431 | "array", | ||
432 | "var_array", | ||
433 | "list", | ||
434 | "hash", | ||
435 | "???" | ||
436 | }; | ||
437 | |||
438 | static const char *eet_node_dump_t_name[14][2] = { | ||
439 | { "???: ", "???" }, | ||
440 | { "char: ", "%hhi" }, | ||
441 | { "short: ", "%hi" }, | ||
442 | { "int: ", "%i" }, | ||
443 | { "long_long: ", "%lli" }, | ||
444 | { "float: ", "%1.25f" }, | ||
445 | { "double: ", "%1.25f" }, | ||
446 | { "uchar: ", "%hhu" }, | ||
447 | { "ushort: ", "%i" }, | ||
448 | { "uint: ", "%u" }, | ||
449 | { "ulong_long: ", "%llu" }, | ||
450 | { "null", "" } | ||
451 | }; | ||
452 | |||
453 | static void | ||
454 | eet_node_dump_level(int level, | ||
455 | Eet_Dump_Callback dumpfunc, | ||
456 | void *dumpdata) | ||
457 | { | ||
458 | int i; | ||
459 | |||
460 | for (i = 0; i < level; i++) dumpfunc(dumpdata, " "); | ||
461 | } /* eet_node_dump_level */ | ||
462 | |||
463 | static char * | ||
464 | eet_node_string_escape(const char *str) | ||
465 | { | ||
466 | char *s, *sp; | ||
467 | const char *strp; | ||
468 | int sz = 0; | ||
469 | |||
470 | for (strp = str; *strp; strp++) | ||
471 | { | ||
472 | if (*strp == '\"') | ||
473 | sz += 2; | ||
474 | else if (*strp == '\\') | ||
475 | sz += 2; | ||
476 | else if (*strp == '\n') | ||
477 | sz += 2; | ||
478 | else | ||
479 | sz += 1; | ||
480 | } | ||
481 | s = malloc(sz + 1); | ||
482 | if (!s) | ||
483 | return NULL; | ||
484 | |||
485 | for (strp = str, sp = s; *strp; strp++, sp++) | ||
486 | { | ||
487 | if (*strp == '\"' | ||
488 | || *strp == '\\' | ||
489 | || *strp == '\n') | ||
490 | { | ||
491 | *sp = '\\'; | ||
492 | sp++; | ||
493 | } | ||
494 | |||
495 | if (*strp == '\n') | ||
496 | *sp = 'n'; | ||
497 | else | ||
498 | *sp = *strp; | ||
499 | } | ||
500 | *sp = 0; | ||
501 | return s; | ||
502 | } /* eet_node_string_escape */ | ||
503 | |||
504 | static void | ||
505 | eet_node_dump_string_escape(void *dumpdata, | ||
506 | Eet_Dump_Callback dumpfunc, | ||
507 | const char *str) | ||
508 | { | ||
509 | char *s; | ||
510 | |||
511 | s = eet_node_string_escape(str); | ||
512 | if (!s) | ||
513 | return; | ||
514 | |||
515 | dumpfunc(dumpdata, s); | ||
516 | free(s); | ||
517 | } /* eet_node_dump_string_escape */ | ||
518 | |||
519 | static void | ||
520 | eet_node_dump_simple_type(Eet_Node *n, | ||
521 | int level, | ||
522 | Eet_Dump_Callback dumpfunc, | ||
523 | void *dumpdata) | ||
524 | { | ||
525 | const char *type_name = NULL; | ||
526 | char tbuf[256]; | ||
527 | |||
528 | eet_node_dump_level(level, dumpfunc, dumpdata); | ||
529 | dumpfunc(dumpdata, "value \""); | ||
530 | eet_node_dump_string_escape(dumpdata, dumpfunc, n->name); | ||
531 | dumpfunc(dumpdata, "\" "); | ||
532 | |||
533 | #ifdef EET_T_TYPE | ||
534 | # undef EET_T_TYPE | ||
535 | #endif /* ifdef EET_T_TYPE */ | ||
536 | |||
537 | #define EET_T_TYPE(Eet_Type, Type) \ | ||
538 | case Eet_Type: \ | ||
539 | { \ | ||
540 | dumpfunc(dumpdata, eet_node_dump_t_name[Eet_Type][0]); \ | ||
541 | snprintf(tbuf, \ | ||
542 | sizeof (tbuf), \ | ||
543 | eet_node_dump_t_name[Eet_Type][1], \ | ||
544 | n->data.value.Type); \ | ||
545 | dumpfunc(dumpdata, tbuf); \ | ||
546 | break; \ | ||
547 | } | ||
548 | |||
549 | switch (n->type) | ||
550 | { | ||
551 | EET_T_TYPE(EET_T_CHAR, c); | ||
552 | EET_T_TYPE(EET_T_SHORT, s); | ||
553 | EET_T_TYPE(EET_T_INT, i); | ||
554 | EET_T_TYPE(EET_T_LONG_LONG, l); | ||
555 | EET_T_TYPE(EET_T_FLOAT, f); | ||
556 | EET_T_TYPE(EET_T_DOUBLE, d); | ||
557 | EET_T_TYPE(EET_T_UCHAR, uc); | ||
558 | EET_T_TYPE(EET_T_USHORT, us); | ||
559 | EET_T_TYPE(EET_T_UINT, ui); | ||
560 | EET_T_TYPE(EET_T_ULONG_LONG, ul); | ||
561 | |||
562 | case EET_T_INLINED_STRING: | ||
563 | type_name = "inlined: \""; | ||
564 | |||
565 | case EET_T_STRING: | ||
566 | if (!type_name) | ||
567 | type_name = "string: \""; | ||
568 | |||
569 | dumpfunc(dumpdata, type_name); | ||
570 | eet_node_dump_string_escape(dumpdata, dumpfunc, n->data.value.str); | ||
571 | dumpfunc(dumpdata, "\""); | ||
572 | break; | ||
573 | |||
574 | case EET_T_NULL: | ||
575 | dumpfunc(dumpdata, "null"); | ||
576 | break; | ||
577 | |||
578 | default: | ||
579 | dumpfunc(dumpdata, "???: ???"); | ||
580 | break; | ||
581 | } /* switch */ | ||
582 | |||
583 | dumpfunc(dumpdata, ";\n"); | ||
584 | } /* eet_node_dump_simple_type */ | ||
585 | |||
586 | static void | ||
587 | eet_node_dump_group_start(int level, | ||
588 | Eet_Dump_Callback dumpfunc, | ||
589 | void *dumpdata, | ||
590 | int group_type, | ||
591 | const char *name) | ||
592 | { | ||
593 | int chnk_type; | ||
594 | |||
595 | chnk_type = (group_type >= EET_G_UNKNOWN && group_type <= EET_G_HASH) ? | ||
596 | group_type : EET_G_LAST; | ||
597 | |||
598 | eet_node_dump_level(level, dumpfunc, dumpdata); | ||
599 | dumpfunc(dumpdata, "group \""); | ||
600 | eet_node_dump_string_escape(dumpdata, dumpfunc, name); | ||
601 | dumpfunc(dumpdata, "\" "); | ||
602 | |||
603 | dumpfunc(dumpdata, eet_node_dump_g_name[chnk_type - EET_G_UNKNOWN]); | ||
604 | dumpfunc(dumpdata, " {\n"); | ||
605 | } /* eet_node_dump_group_start */ | ||
606 | |||
607 | static void | ||
608 | eet_node_dump_group_end(int level, | ||
609 | Eet_Dump_Callback dumpfunc, | ||
610 | void *dumpdata) | ||
611 | { | ||
612 | eet_node_dump_level(level, dumpfunc, dumpdata); | ||
613 | dumpfunc(dumpdata, "}\n"); | ||
614 | } /* eet_node_dump_group_end */ | ||
615 | |||
616 | void | ||
617 | eet_node_dump(Eet_Node *n, | ||
618 | int dumplevel, | ||
619 | Eet_Dump_Callback dumpfunc, | ||
620 | void *dumpdata) | ||
621 | { | ||
622 | Eet_Node *it; | ||
623 | |||
624 | if (!n) | ||
625 | return; | ||
626 | |||
627 | switch (n->type) | ||
628 | { | ||
629 | case EET_G_VAR_ARRAY: | ||
630 | case EET_G_ARRAY: | ||
631 | case EET_G_UNKNOWN: | ||
632 | case EET_G_HASH: | ||
633 | case EET_G_LIST: | ||
634 | eet_node_dump_group_start(dumplevel, | ||
635 | dumpfunc, | ||
636 | dumpdata, | ||
637 | n->type, | ||
638 | n->name); | ||
639 | |||
640 | if (n->type == EET_G_VAR_ARRAY | ||
641 | || n->type == EET_G_ARRAY) | ||
642 | { | ||
643 | char tbuf[256]; | ||
644 | |||
645 | eet_node_dump_level(dumplevel, dumpfunc, dumpdata); | ||
646 | dumpfunc(dumpdata, " count "); | ||
647 | eina_convert_itoa(n->count, tbuf); | ||
648 | dumpfunc(dumpdata, tbuf); | ||
649 | dumpfunc(dumpdata, ";\n"); | ||
650 | } | ||
651 | else if (n->type == EET_G_HASH) | ||
652 | { | ||
653 | eet_node_dump_level(dumplevel, dumpfunc, dumpdata); | ||
654 | dumpfunc(dumpdata, " key \""); | ||
655 | eet_node_dump_string_escape(dumpdata, dumpfunc, n->key); | ||
656 | dumpfunc(dumpdata, "\";\n"); | ||
657 | } | ||
658 | |||
659 | for (it = n->values; it; it = it->next) | ||
660 | eet_node_dump(it, dumplevel + 2, dumpfunc, dumpdata); | ||
661 | |||
662 | eet_node_dump_group_end(dumplevel, dumpfunc, dumpdata); | ||
663 | break; | ||
664 | |||
665 | case EET_T_STRING: | ||
666 | case EET_T_INLINED_STRING: | ||
667 | case EET_T_CHAR: | ||
668 | case EET_T_SHORT: | ||
669 | case EET_T_INT: | ||
670 | case EET_T_LONG_LONG: | ||
671 | case EET_T_FLOAT: | ||
672 | case EET_T_DOUBLE: | ||
673 | case EET_T_UCHAR: | ||
674 | case EET_T_USHORT: | ||
675 | case EET_T_UINT: | ||
676 | case EET_T_ULONG_LONG: | ||
677 | eet_node_dump_simple_type(n, dumplevel, dumpfunc, dumpdata); | ||
678 | break; | ||
679 | } /* switch */ | ||
680 | } /* eet_node_dump */ | ||
681 | |||
682 | void * | ||
683 | eet_node_walk(void *parent, | ||
684 | const char *name, | ||
685 | Eet_Node *root, | ||
686 | Eet_Node_Walk *cb, | ||
687 | void *user_data) | ||
688 | { | ||
689 | Eet_Node *it; | ||
690 | void *me = NULL; | ||
691 | int i; | ||
692 | |||
693 | if (!root) | ||
694 | { | ||
695 | if (parent) | ||
696 | cb->struct_add(parent, name, NULL, user_data); | ||
697 | |||
698 | return NULL; | ||
699 | } | ||
700 | |||
701 | switch (root->type) | ||
702 | { | ||
703 | case EET_G_UNKNOWN: | ||
704 | me = cb->struct_alloc(root->name, user_data); | ||
705 | |||
706 | for (it = root->values; it; it = it->next) | ||
707 | eet_node_walk(me, it->name, it, cb, user_data); | ||
708 | |||
709 | break; | ||
710 | |||
711 | case EET_G_VAR_ARRAY: | ||
712 | case EET_G_ARRAY: | ||
713 | me = cb->array(root->type == EET_G_VAR_ARRAY ? EINA_TRUE : EINA_FALSE, | ||
714 | root->name, root->count, user_data); | ||
715 | |||
716 | for (i = 0, it = root->values; it; it = it->next) | ||
717 | cb->insert(me, i++, eet_node_walk(NULL, | ||
718 | NULL, | ||
719 | it, | ||
720 | cb, | ||
721 | user_data), user_data); | ||
722 | |||
723 | break; | ||
724 | |||
725 | case EET_G_LIST: | ||
726 | me = cb->list(root->name, user_data); | ||
727 | |||
728 | for (it = root->values; it; it = it->next) | ||
729 | cb->append(me, eet_node_walk(NULL, | ||
730 | NULL, | ||
731 | it, | ||
732 | cb, | ||
733 | user_data), user_data); | ||
734 | |||
735 | break; | ||
736 | |||
737 | case EET_G_HASH: | ||
738 | if (!parent) | ||
739 | return NULL; | ||
740 | |||
741 | return cb->hash(parent, root->name, root->key, | ||
742 | eet_node_walk(NULL, | ||
743 | NULL, | ||
744 | root->values, | ||
745 | cb, | ||
746 | user_data), user_data); | ||
747 | |||
748 | case EET_T_STRING: | ||
749 | case EET_T_INLINED_STRING: | ||
750 | case EET_T_CHAR: | ||
751 | case EET_T_SHORT: | ||
752 | case EET_T_INT: | ||
753 | case EET_T_LONG_LONG: | ||
754 | case EET_T_FLOAT: | ||
755 | case EET_T_DOUBLE: | ||
756 | case EET_T_UCHAR: | ||
757 | case EET_T_USHORT: | ||
758 | case EET_T_UINT: | ||
759 | case EET_T_ULONG_LONG: | ||
760 | me = cb->simple(root->type, &root->data, user_data); | ||
761 | break; | ||
762 | } /* switch */ | ||
763 | |||
764 | if (parent) | ||
765 | cb->struct_add(parent, name, me, user_data); | ||
766 | |||
767 | return me; | ||
768 | } /* eet_node_walk */ | ||
769 | |||
770 | int | ||
771 | eet_node_init(void) | ||
772 | { | ||
773 | const char *choice; | ||
774 | const char *tmp; | ||
775 | |||
776 | #ifdef EINA_DEFAULT_MEMPOOL | ||
777 | choice = "pass_through"; | ||
778 | #else | ||
779 | choice = "chained_mempool"; | ||
780 | #endif | ||
781 | tmp = getenv("EET_MEMPOOL"); | ||
782 | if (tmp && tmp[0]) | ||
783 | choice = tmp; | ||
784 | |||
785 | _eet_node_mp = | ||
786 | eina_mempool_add(choice, "eet-node-alloc", NULL, sizeof(Eet_Node), 1024); | ||
787 | |||
788 | return _eet_node_mp ? 1 : 0; | ||
789 | } /* eet_node_init */ | ||
790 | |||
791 | void | ||
792 | eet_node_shutdown(void) | ||
793 | { | ||
794 | eina_mempool_del(_eet_node_mp); | ||
795 | _eet_node_mp = NULL; | ||
796 | } /* eet_node_shutdown */ | ||
797 | |||
diff --git a/libraries/eet/src/lib/eet_utils.c b/libraries/eet/src/lib/eet_utils.c new file mode 100644 index 0000000..8e591a2 --- /dev/null +++ b/libraries/eet/src/lib/eet_utils.c | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif /* ifdef HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <stdio.h> | ||
6 | #include <math.h> | ||
7 | |||
8 | #include "Eet.h" | ||
9 | #include "Eet_private.h" | ||
10 | |||
11 | int | ||
12 | _eet_hash_gen(const char *key, | ||
13 | int hash_size) | ||
14 | { | ||
15 | int hash_num = 0; | ||
16 | int value, i; | ||
17 | int mask; | ||
18 | unsigned char *ptr; | ||
19 | |||
20 | /* no string - index 0 */ | ||
21 | if (!key) | ||
22 | return 0; | ||
23 | |||
24 | /* calc hash num */ | ||
25 | for (i = 0, ptr = (unsigned char *)key, value = (int)(*ptr); | ||
26 | value; | ||
27 | ptr++, i++, value = (int)(*ptr)) | ||
28 | hash_num ^= (value | (value << 8)) >> (i & 0x7); | ||
29 | |||
30 | /* mask it */ | ||
31 | mask = (1 << hash_size) - 1; | ||
32 | hash_num &= mask; | ||
33 | /* return it */ | ||
34 | return hash_num; | ||
35 | } /* _eet_hash_gen */ | ||
36 | |||