From fea591fcb8c4f2eeb843b246e5a4fcc08ede60fd Mon Sep 17 00:00:00 2001 From: HyungKyu Song Date: Sat, 16 Feb 2013 00:17:40 +0900 Subject: [PATCH] Tizen 2.0 Release --- AUTHORS | 13 + COPYING | 45 +- ChangeLog | 560 ++- INSTALL | 245 +- Makefile.am | 91 +- NEWS | 75 +- README | 68 + autogen.sh | 26 +- configure.ac | 541 +++ debian/changelog | 460 +++ debian/compat | 2 +- debian/control | 10 +- debian/copyright | 41 +- debian/jobs | 0 debian/libeet-dev.install | 1 + debian/libeet1.symbols | 85 + debian/rules | 26 +- doc/Doxyfile.in | 1694 ++++++++ doc/Makefile.am | 63 +- doc/e.css | 591 ++- doc/eet.dox.in | 0 doc/examples.dox | 184 + doc/foot.html | 22 +- doc/head.html | 103 +- doc/img/e.png | Bin 0 -> 3825 bytes doc/img/e_big.png | Bin 0 -> 30052 bytes doc/img/edoxy.css | 966 +++++ doc/img/foot_bg.png | Bin 0 -> 173 bytes doc/img/head_bg.png | Bin 0 -> 214 bytes doc/img/menu_bg.png | Bin 0 -> 192 bytes doc/img/menu_bg_current.png | Bin 0 -> 1200 bytes doc/img/menu_bg_hover.png | Bin 0 -> 3278 bytes doc/img/menu_bg_last.png | Bin 0 -> 637 bytes doc/img/menu_bg_unsel.png | Bin 0 -> 1596 bytes eet.manifest | 5 + eet.pc.in | 5 +- eet.spec.in | 12 +- m4/ac_attribute.m4 | 47 + m4/ac_path_generic.m4 | 137 + m4/efl_binary.m4 | 79 + m4/efl_check_funcs.m4 | 435 +++ m4/efl_check_libs.m4 | 119 + m4/efl_compiler_flag.m4 | 57 + m4/efl_doxygen.m4 | 94 + m4/efl_path_max.m4 | 36 + m4/efl_tests.m4 | 65 + packaging/eet.spec | 102 + src/Makefile.am | 2 +- src/bin/Makefile.am | 10 +- src/bin/eet_main.c | 446 ++- src/examples/Makefile.am | 50 + src/examples/eet-basic.c | 40 + src/examples/eet-data-cipher_decipher.c | 119 + src/examples/eet-data-file_descriptor_01.c | 529 +++ src/examples/eet-data-file_descriptor_02.c | 944 +++++ src/examples/eet-data-nested.c | 272 ++ src/examples/eet-data-simple.c | 224 ++ src/examples/eet-file.c | 127 + src/lib/Eet.h | 5426 ++++++++++++++++++++------ src/lib/Eet_private.h | 371 +- src/lib/Makefile.am | 37 +- src/lib/eet_alloc.c | 93 + src/lib/eet_cipher.c | 1391 +++++++ src/lib/eet_connection.c | 232 ++ src/lib/eet_data.c | 5751 +++++++++++++++++++--------- src/lib/eet_dictionary.c | 509 ++- src/lib/eet_image.c | 2180 +++++++---- src/lib/eet_lib.c | 2932 +++++++++----- src/lib/eet_node.c | 797 ++++ src/lib/eet_utils.c | 197 +- src/lib/lz4/README | 7 + src/lib/lz4/lz4.c | 863 +++++ src/lib/lz4/lz4.h | 117 + src/lib/lz4/lz4hc.c | 671 ++++ src/lib/lz4/lz4hc.h | 60 + src/tests/Makefile.am | 15 +- src/tests/cert.pem | 22 + src/tests/eet_data_suite.c | 180 +- src/tests/eet_suite.c | 2408 ++++++++++-- src/tests/eet_suite.h | 16 +- src/tests/key.pem | 15 + src/tests/key_enc.pem | 17 + src/tests/key_enc_none.pem | 16 + 83 files changed, 27899 insertions(+), 6292 deletions(-) create mode 100644 README create mode 100644 configure.ac create mode 100644 debian/changelog create mode 100644 debian/jobs create mode 100644 debian/libeet1.symbols mode change 100644 => 100755 debian/rules create mode 100644 doc/Doxyfile.in create mode 100644 doc/eet.dox.in create mode 100644 doc/examples.dox create mode 100755 doc/img/e.png create mode 100755 doc/img/e_big.png create mode 100755 doc/img/edoxy.css create mode 100755 doc/img/foot_bg.png create mode 100755 doc/img/head_bg.png create mode 100755 doc/img/menu_bg.png create mode 100755 doc/img/menu_bg_current.png create mode 100755 doc/img/menu_bg_hover.png create mode 100755 doc/img/menu_bg_last.png create mode 100755 doc/img/menu_bg_unsel.png create mode 100644 eet.manifest create mode 100644 m4/ac_attribute.m4 create mode 100644 m4/ac_path_generic.m4 create mode 100644 m4/efl_binary.m4 create mode 100644 m4/efl_check_funcs.m4 create mode 100644 m4/efl_check_libs.m4 create mode 100644 m4/efl_compiler_flag.m4 create mode 100644 m4/efl_doxygen.m4 create mode 100644 m4/efl_path_max.m4 create mode 100644 m4/efl_tests.m4 create mode 100644 packaging/eet.spec create mode 100644 src/examples/Makefile.am create mode 100644 src/examples/eet-basic.c create mode 100644 src/examples/eet-data-cipher_decipher.c create mode 100644 src/examples/eet-data-file_descriptor_01.c create mode 100644 src/examples/eet-data-file_descriptor_02.c create mode 100644 src/examples/eet-data-nested.c create mode 100644 src/examples/eet-data-simple.c create mode 100644 src/examples/eet-file.c create mode 100644 src/lib/eet_alloc.c create mode 100644 src/lib/eet_cipher.c create mode 100644 src/lib/eet_connection.c create mode 100644 src/lib/eet_node.c create mode 100644 src/lib/lz4/README create mode 100644 src/lib/lz4/lz4.c create mode 100644 src/lib/lz4/lz4.h create mode 100644 src/lib/lz4/lz4hc.c create mode 100644 src/lib/lz4/lz4hc.h create mode 100644 src/tests/cert.pem create mode 100644 src/tests/key.pem create mode 100644 src/tests/key_enc.pem create mode 100644 src/tests/key_enc_none.pem diff --git a/AUTHORS b/AUTHORS index c491082..9e2d1aa 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,3 +1,16 @@ The Rasterman (Carsten Haitzler) David Goodlad Cedric Bail +Arnaud de Turckheim +Luis Felipe Strano Moraes +Chidambar Zinnoury +Vincent Torri +Gustavo Sverzut Barbieri +Raphael Kubo da Costa +Mathieu Taillefumier +Albin "Lutin" Tonnerre +Adam Simpkins +Mike Blumenkrantz +Lionel Orry +Jérôme Pinot +Leandro Santiago diff --git a/COPYING b/COPYING index 474fcc5..296efe7 100644 --- a/COPYING +++ b/COPYING @@ -1,28 +1,25 @@ -Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS) +Copyright notice for Eet: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (C) 2002-2011 Carsten Haitzler and various contributors (see AUTHORS) -The above copyright notice and this permission notice shall be included in -all copies of the Software and its Copyright notices. In addition publicly -documented acknowledgment must be given that this software has been used if no -source code of this software is made available publicly. This includes -acknowledgments in either Copyright notices, Manuals, Publicity and Marketing -documents or any documentation provided with any product containing this -software. This License does not apply to any software that links to the -libraries provided by this software (statically or dynamically), but only to -the software provided. +All rights reserved. -Please see the COPYING.PLAIN for a plain-english explanation of this notice -and it's intent. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/ChangeLog b/ChangeLog index 0569349..6afdc47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,7 +10,7 @@ 2008-05-14 Cedric BAIL - * Fix convertion from a text to a hash (EET_G_HASH). + * Fix conversion from a text to a hash (EET_G_HASH). * Fix inlined string (EET_T_INLINED_STRING) dump/undump by introducing the new word for the parser 'inlined'. @@ -84,3 +84,561 @@ with Microsoft tools. Written by Dmitriy Mazovka. + +2008-08-20 Cedric BAIL + + * Fix the dictionnary check during eet_open. + +2008-08-22 Cedric BAIL + + * Fix memory leaks in eet_data strings + +2008-09-03 Cedric BAIL + + * Fix inline-jpeg decode to use mem buf, not tmp-file on platforms that + don't support mem_open() etc. + * Add eet_memopen_read() to be able to open an eet file already + mapped in memory (eg compiled-in or mmaped some other way). + +2008-09-11 Cedric BAIL + + * Improve hash generation speed for big files. + * Inline more functions explicitly for speed. + +2008-09-25 Carsten Haitzler (The Rasterman) + + 1.1.0 release + +2008-10-20 Cedric BAIL + + * Make use of eina. + +2008-10-23 Cedric BAIL + + * Fix string in list and hash. + +2008-10-24 Cedric BAIL + + * Fix array in eet_data. + +2008-11-13 Cedric BAIL + + * Add crypto support to eet with OpenSSL. + +2008-11-13 Arnaud de Turckheim + + * Add GNUtls support to eet. + +2008-11-14 Cedric BAIL + + * Make password callback work with GNUtls. + +2008-11-26 Cedric BAIL + + * Add a function to retrieve raw signature. + +2009-01-30 Cedric BAIL + + * Fix a corrupted pointer use in eet_cipher.c + +2009-02-09 Chidambar Zinnoury + + * Add some missing __UNUSED__ flags. + +2009-02-26 Luis Felipe Strano Moraes + + * Fix problem reported by llvm + +2009-03-09 Cedric BAIL + + * Add sha1 retrieval for an Eet_File. + +2009-03-17 Gustavo Sverzut Barbieri + + * Force fsync() after data is written to file, solve ext4 issues. + +2009-03-18 Carsten Haitzler (The Rasterman) + + * Disable fsync. Edit the code if you need it. + +2009-03-19 Cedric BAIL + + * Make eet_data thread safe. + +2009-03-25 Cedric BAIL + + * Fix eet pkg-config dependencies. + * Fix double init of gcry. + +2009-04-22 Carsten Haitzler (The Rasterman) + + * Release eet 1.2.0 + +2009-05-18 Cedric BAIL + + * Cleanup Eet_Data code. + +2009-06-02 Cedric BAIL + + * Make eet_node API usable. + +2009-06-14 Carsten Haitzler (The Rasterman) + + * Release eet 1.2.1 + +2009-07-08 Cedric BAIL + + * Reorder gcry init to be used during gnutls init. + +2009-07-11 Hanspeter Portner + + * Improve docs/examples in Eet.h + +2009-07-23 Cedric BAIL + + * Fix init on system without SECMEM. + +2009-07-29 Carsten Haitzler (The Rasterman) + + * Release eet 1.2.2 + +2009-08-13 Cedric BAIL + + * Deprecating eet_data_descriptor*_new. + * Add eet_data_descriptor_stream_new and eet_data_descriptor_file_new. + * Add eina helper. + * Cleanup Eet_Data_Descriptor code. + +2009-08-16 Carsten Haitzler (The Rasterman) + + * Fix eet data encode to encode empty structs etc. so save saves + something as opposed to nothing + +2009-08-16 Carsten Haitzler (The Rasterman) + + * Fix documentation of eet_data_write() and eet_write() for return + value to return # of bytes written, not 1 or 0 + +2009-08-16 Vincent Torri + + * Fix build with suncc (missing alloca() declaration in eet_cipher.c) + +2009-09-15 Mathieu Taillefumier + + * Use new Eina_Log infrastructure to report error. + +2009-09-15 Cedric BAIL + + * Remove apparently useless eet_freeleak_* from eet_data. + +2009-09-29 Cedric BAIL + + * Add Fixed Point support and make it possible to switch from float + and double to any fixed point variant supported by eina. + + Note: File saved with fixed point could be read by older version of + eet library with EET_T_DOUBLE type. + +2009-10-01 Mathieu Taillefumier + + * remove useless Eina_Log macros. + +2009-10-01 Vincent Torri + + * Check the returned value of eet_init() in the binary. + * Use binary mode of fopen() in eet_main() for Windows compatibility. + +2009-10-09 Vincent Torri + + * initialize eina first in eet_init(). + +2009-11-02 Vincent Torri + + * allow generation of one single file with all source code in it. + See configure help to enable it (--enable-amalgamation). + +2009-11-11 Vincent Torri + + * Add check on libgcrypt library in configure. Needed when GNUtls + support is enabled. + +2009-12-02 Carsten Haitzler (The Rasterman) + + * Release eet 1.2.3 + +2009-12-03 Cedric BAIL + + * Make all operation on Eet_File thread safe. + +2009-12-07 Cedric BAIL + + * Fix error when retrieving a different float type than the stored one. + * Reduce conversion with a little memory overhead. + +2009-12-07 Vincent Torri + + * Include winsock2.h in eet_image.c for htonl definition on Windows. + * Fix Visual Studio project files + +2009-12-11 Cedric BAIL + + * Make eet_data_descriptor_free safe to call on NULL pointer. + +2009-12-21 Cedric BAIL + + * More work on eet_node dump code. + +2009-12-28 Cedric BAIL + + * Add fully functionnal eet_node dump code. + +2009-12-29 Cedric BAIL + + * Don't mess up when memory realloc failed during data descriptor creation. + +2010-01-04 Carsten Haitzler (The Rasterman) + + * Fix another thread deadlock in mutex handling even in a single-threaded app. + +2010-01-12 Cedric BAIL + + * Rewrite Eet_Data. Now you can do list/hash/array of strings and all + the test suite is passing. + * Add eet_data_node_decode_cipher and eet_data_node_read_cipher. + +2010-01-15 Cedric BAIL + + * Fix amalgamation. + +2010-01-16 Vincent Torri + + * eet_cipher.c: Fix arithmetic pointer on void * + +2010-01-17 Cedric BAIL + + * Add a mempool for Eet_Node. + +2010-01-21 Cedric BAIL + + * Add experimental API to walk Eet_Node tree. + +2010-01-22 Cedric BAIL + + * Add VAR_ARRAY tests. + +2010-01-27 Cedric BAIL + + * Improve security by zeroying cipher material as soon as possible. + +2010-01-27 Cedric BAIL + + * Improve security by zeroying cipher material as soon as possible. + +2010-03-01 Albin Tonnerre + + * Fix override of global symbols. + +2010-03-15 Adam Simpkins / Cedric BAIL + + * Fix clearcache race condition. + +2010-04-02 Cedric BAIL + + * Fix eet_data_node_read_cipher return type. + * Add Eet_Connection. + +2010-04-07 Cedric BAIL + + * Improve eet_eina_file_data_descriptor_class_set by using + eina_hash_direct_add to avoid duplication hash key string. + +2010-04-08 Cedric BAIL + + * Fix file corruption reported by Tiago Falcao + +2010-04-09 Cedric BAIL + + * Add eet_sync. + * Only delete the file at the last possible time. + * Reduce open file descriptor. + +2010-04-16 Cedric BAIL + + * Handle fixed point in data stream. + +2010-04-21 Cedric BAIL + + * Add EET_G_UNION and EET_G_VARIANT. + +2010-05-29 Carsten Haitzler (The Rasterman) + + * Add EET_VERSION_MAJOR, EET_VERSION_MINOR. + * Add Eet_Version, eet_version. + * Make configure.ac use m4 defines for version + * Support SVN revision in version check + +2010-06-07 Carsten Haitzler (The Rasterman) + + * Release eet 1.3.0 + +2010-06-27 Carsten Haitzler (The Rasterman) + + * Release eet 1.3.2 + +2010-06-29 Vincent Torri + + * On Windows 64, long is of size 32 bits and not 64 bits. Also + LONG_BIT is not defined on Windows. + +2010-06-29 Cedric BAIL + + * Add eet_alias support. + * Fix possible dead lock in eet_write_cipher. + +2010-07-08 Carsten Haitzler (The Rasterman) + + * Moved Eet.h into $includedir/eet-MAJOR_VERSION/ + +2010-07-15 Vincent Torri + + * Add native Windows thread support instead of using pthread + (less overhead). On other OS, pthread is still used by default. + Pass --enable-win32-threads to activate thread support on + Windows. + +2010-07-20 Cedric BAIL + + * Improve file change detection in eet_open by checking size also. + +2010-08-02 Cedric BAIL + + * Fix bug in eet_connection code when running on 32bits machine. + +2010-08-06 Cedric BAIL + + * Add EET_DATA_DESCRIPTOR_ADD_HASH_STRING. + +2010-08-06 Cedric BAIL + + * Break eet_eina_* function helper to provide a clean API/ABI to + prevent futur break. This should prevent the ABI break that was + introduced with release 1.3.0. + + * Add a specific allocator for array. This should fix wrong allocation + case discovered with recent edje file format change. + +2010-08-23 Carsten Haitzler (The Rasterman) + + * Fix some cppcheck complaints - all of them bogus though. + Nothing actually fixed. + +2010-08-27 Cedric BAIL + + * Prevent the build of eet data structure that doesn't match what + the application is expecting. + +2010-09-02 Cedric BAIL + + * Fix bug of ever growing dictionnary and improve strcmp comparison. + +2010-11-12 Cedric BAIL + + * Don't try to read broken file when open in READ_WRITE mode. + +2010-11-14 Cedric BAIL + + * Fix bug with cypher and compression used together. + +2010-11-21 Carsten Haitzler (The Rasterman) + + * Fix another bug related to cipher and compression (leak and + bad free) + +2010-11-25 Cedric BAIL + + * Add EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY_STRING. + +2010-11-26 Cedric BAIL + + * Reduce memory used by Eet dictionary. + +2010-11-29 Cedric BAIL + + * Improve speed of Eet_String users. It does impact all string + encoding/decoding, but even faster for stringshare encoding. + + * Improve speed when decoding mostly array with eet_data_read. + +2010-12-03 Cedric BAIL + + * Improve portability. + +2010-12-07 Carsten Haitzler (The Rasterman) + + * Move raw function pointer defs to typedefs in public API for + readability improvements. + +2011-01-29 Carsten Haitzler (The Rasterman) + + * 1.4.0 release + +2011-01-29 Vincent Torri + + * Use eina_stringshare_add() instead of strdup() on mmaped file names + on Windows. This fix eet shut down on Windows. + +2011-02-14 Cedric BAIL + + * Improve Eet_Data to make decoding of EET_G_UNION and EET_G_*ARRAY + faster and less memory heavy. + +2011-05-14 Cedric BAIL + + * Use Eina_Lock. + * Sync GNUTLS initialisation with Eina. + +2011-05-17 Cedric BAIL + + * Use Eina_File. + * Fix test forgetting to initialize eet. + +2011-05-23 Vincent Torri + + * Fix compilation with libjpeg 8 on Windows. + +2011-06-10 Cedric BAIL + + * Add EET_DATA_DESCRIPTOR_ADD_LIST_STRING helper to define List of char *. + +2011-07-04 Mike Blumenkrantz + + * Add functions to manipulate nodes: + eet_node_children_get, eet_node_next_get, eet_node_parent_get, + eet_node_type_get, eet_node_value_get, eet_node_name_get + * Fix segmentation faults in several eet_node functions + +2011-07-16 Vincent Torri + + * On Windows, open() in text mode followed by fdopen() in + binary mode does not create a stream in binary mode. + So add O_BINARY to open(). + +2011-07-29 Mike Blumenkrantz + + * Add eet_alias_get to return the destination name of an alias + +2011-09-15 Cedric Bail + + * Add eet_data_xattr_cipher_get and eet_data_xattr_cipher_set. + +2011-10-04 Carsten Haitzler (The Rasterman) + + * Fix issue where an empty eet file (no keys) is not openable + for read/write anymore. Allow it. + +2011-10-28 David Seikel (onefang) + + * Added a new macro for adding arrays of basic types. + EET_DATA_DESCRIPTOR_ADD_BASIC_ARRAY + +2011-11-16 Carsten Haitzler (The Rasterman) + + * JPEG encode and decode in eet now uses ISLOW (not IFAST) due to + noticable quality losses in the chase for speed. It will use + IFAST for quality less than 60 when encoding + +2011-12-02 Carsten Haitzler (The Rasterman) + + 1.5.0 release + +2011-12-02 Mike Blumenkrantz + + * added eet_file_get to return the filename of an Eet_File + * Eet_File filenames are now stringshared + * added mempool allocators + +2011-12-29 Carsten Haitzler (The Rasterman) + + * increase eet_connection packet size to 1Mb - more reasonable. + +2012-01-07 Boris Faure (billiob) + + * make eet tool write to standard output if no output file given. + +2012-02-09 Cedric Bail + + * add support for GNUTLS 3.x. + +2012-02-10 Cedric Bail + + * add eet_dictionary_count. + * add "eet -t FILE.EET". + +2012-03-29 David Seikel (onefang) + + * Added a new macro for adding variable arrays of basic types. + EET_DATA_DESCRIPTOR_ADD_BASIC_VAR_ARRAY + +2012-04-26 Carsten Haitzler (The Rasterman) + + 1.6.0 release + +2012-05-11 Cedric Bail + + * Force destruction of all pending file when shuting down eet. + +2012-05-14 Carsten Haitzler (The Rasterman) + + * Add LZ4/LZ4HC compression & decompression capabilities + +2012-05-15 Cedric Bail + + * Make eet_dictionary thread safe. + +2012-05-30 Cedric Bail + + * Check that gnutls and openssl don't return below zero size during decipher. + +2012-06-27 Leandro Santiago + + * Fix crash when cyphering huge amount of data. + +2012-07-16 Cedric Bail + + * Add code to detect overrun and underrun in eet_data_descriptor_element_add. + * Fix possible wrong size decoding for simple type. + +2012-08-09 Cedric Bail + + * Don't copy string around for nothing. + +2012-08-22 Igor Murzov (GArik_) + + * Fixed memory leak of eet_data_chunk_put(). + +2012-08-24 Cedric Bail + + * Add eet_connection_empty. + +2012-08-26 Cedric Bail + + * Correctly initialize dictionary correctly. + +2012-08-30 Carsten Haitzler (The Rasterman) + + 1.7.0 release + +2012-09-21 Carsten Haitzler (The Rasterman) + + * Fix big endian bug with eet image handling and endianess swapping. + +2012-09-27 Patryk Kaczmarek + + * Add eet file handle null checks to eet_data_write_cipher(), + eet_data_descriptor_decode_cipher(), + eet_data_descriptor_encode_cipher(), eet_data_xattr_cipher_get(), + eet_data_xattr_cipher_set(). + +2012-10-04 Vincent Torri + + * Update lz4 code to rev. 77. This fix compilation on NetBSD 5.0 diff --git a/INSTALL b/INSTALL index df426ed..23e5f25 100644 --- a/INSTALL +++ b/INSTALL @@ -1,47 +1,236 @@ -COMPILING and INSTALLING: +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free +Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + +By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. -If you got a official release tar archive do: - ./configure +Specifying the System Type +========================== -( otherwise if you got this from enlightenment cvs do: ./autogen.sh ) +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: -Then to compile: - make + CPU-COMPANY-SYSTEM -To install (run this as root, or the user who handles installs): - make install +where SYSTEM can have one of these forms: -To run the unit tests (See Note 5 below): - make check + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. -To get the coverage report (See Notes 6 and 7 below): - make coverage +Sharing Defaults +================ -The report is created in the coverage/ subdir +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). Here is a another example: + /bin/bash ./configure CONFIG_SHELL=/bin/bash + +Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent +configuration-related scripts to be executed by `/bin/bash'. +`configure' Invocation +====================== -NOTE 1: You MUST make install Eet for it to run properly. +`configure' recognizes the following options to control how it operates. -NOTE 2: For compilation with MinGW, fnmatch.h is probably missing. - That file can be found here: -http://www.koders.com/c/fid2B518462CB1EED3D4E31E271DB83CD1582F6EEBE.aspx - It should be installed in the mingw include directory. +`--help' +`-h' + Print a summary of the options to `configure', and exit. -NOTE 3: For compilation with mingw32ce, run configure with the option +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. ---host=arm-wince-mingw32ce +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. -NOTE 4: For compilation with cegcc, follow the wiki: +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. -http://wiki.enlightenment.org/index.php/Category:EFL_Windows_CE +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). -NOTE 5: If you want to be able to run make check, you need library check - from http://check.sourceforge.net/. +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. -NOTE 6: If you want to be able to run coverage test over eet, you will need - gcov (usually any distro provides it) and lcov from - http://ltp.sourceforge.net/coverage/lcov.php. +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. -NOTE 7: For coverage support you also need check support. diff --git a/Makefile.am b/Makefile.am index 76993fd..79b2a28 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,20 +1,23 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = src +SUBDIRS = src doc MAINTAINERCLEANFILES = \ Makefile.in \ aclocal.m4 \ compile \ config.guess \ -config.h.in \ -config.sub \ -configure \ +config.h.in \ +config.h.in~ \ +config.sub \ +configure \ depcomp \ install-sh \ -ltmain.sh \ -missing \ -eet_docs.tar.gz \ +ltmain.sh \ +missing \ +$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.gz \ +$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.bz2 \ +$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-doc.tar.bz2 \ m4/libtool.m4 \ m4/lt~obsolete.m4 \ m4/ltoptions.m4 \ @@ -24,63 +27,63 @@ m4/ltversion.m4 EXTRA_DIST = \ AUTHORS \ COPYING \ -COPYING-PLAIN \ autogen.sh \ -eet.c.in \ eet.pc.in \ eet.spec.in \ eet.spec \ -README.in \ -README \ -Doxyfile \ -doc \ -gendoc +m4/ac_attribute.m4 \ +m4/ac_path_generic.m4 \ +m4/efl_binary.m4 \ +m4/efl_check_funcs.m4 \ +m4/efl_check_libs.m4 \ +m4/efl_doxygen.m4 \ +m4/efl_tests.m4 \ +m4/efl_path_max.m4 pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = eet.pc +.PHONY: doc -if EET_ENABLE_TESTS +# Documentation -check-local: - @./src/tests/eet_suite +doc: + @echo "entering doc/" + $(MAKE) -C doc doc -else +# Unit tests -check-local: - @echo "reconfigure with --enable-tests" +if EFL_ENABLE_TESTS -endif - -if EET_ENABLE_COVERAGE lcov-reset: - @rm -rf coverage - @find . -name "*.gcda" -exec rm {} \; - @lcov --directory . --zerocounters + @rm -rf $(top_builddir)/coverage + @find $(top_builddir) -name "*.gcda" -delete + @lcov --zerocounters --directory $(top_builddir) lcov-report: - @mkdir coverage - @lcov --compat-libtool --directory . --capture --output-file coverage/coverage.info - @lcov -l coverage/coverage.info | grep -v "`cd $(top_srcdir) && pwd`" | cut -d: -f1 > coverage/remove - @lcov -r coverage/coverage.info `cat coverage/remove` > coverage/coverage.cleaned.info - @rm coverage/remove - @mv coverage/coverage.cleaned.info coverage/coverage.info - @genhtml -t "$(PACKAGE_STRING)" -o coverage coverage/coverage.info - -coverage: - @make lcov-reset - @make check - @make lcov-report + @mkdir $(top_builddir)/coverage + lcov --capture --compat-libtool --output-file $(top_builddir)/coverage/coverage.info --directory $(top_builddir) + lcov --remove $(top_builddir)/coverage/coverage.info '*.h' --output-file $(top_builddir)/coverage/coverage.cleaned.info + genhtml -t "$(PACKAGE_STRING)" -o $(top_builddir)/coverage/html $(top_builddir)/coverage/coverage.cleaned.info + @echo "Coverage Report at $(top_builddir)/coverage/html" + +check-local: + @$(MAKE) lcov-reset + @./src/tests/eet_suite + @$(MAKE) lcov-report -clean-local: - @rm -rf coverage else + lcov-reset: - @echo "reconfigure with --enable-gcov" + @echo "reconfigure with --enable-tests" lcov-report: - @echo "reconfigure with --enable-gcov" + @echo "reconfigure with --enable-tests" + +check-local: + @echo "reconfigure with --enable-tests" -coverage: - @echo "reconfigure with --enable-tests --enable-gcov" endif + +clean-local: + @rm -rf coverage diff --git a/NEWS b/NEWS index eecaa10..fdd882d 100644 --- a/NEWS +++ b/NEWS @@ -1,2 +1,73 @@ -2008-04-20 - 1.0.0 Eet Release +Eet 1.7.1 + +Changes since Eet 1.7.0: +-------------------------- + +Fixes: + * Fix PPC (big endian) image codec bug. + +Changes since Eet 1.6.0: +-------------------------- + +Additions: + * Add code to detect overrun and underrun during Eet Data Descriptor setup. + * Add eet_connection_empty. + +Fixes: + * Force destruction of all pending file when shuting down eet. + * Make eet_dictionary thread safe. + * Check that gnutls and openssl don't return below zero size during decipher. + * Fix crash when cyphering huge amount of data. + * Possible wrong size decoding of simple type. + * Don't strdup string around for nothing. + * Always initialize dictionary correctly. + * Fixed memory leak of eet_data_chunk_put(). + +Eet 1.6.0 + +Changes since Eet 1.5.0: +-------------------------- + +Additions: + * eet_file_get to return filenames of Eet_Files. + * added support for GNUTLS 3.x. + * eet_dictionary_count. + * EET_DATA_DESCRIPTOR_ADD_BASIC_VAR_ARRAY API + +Improvements: + + * most allocations moved to mempools. + * support GNUTLS 3.x. + * add "eet -t FILE.EET" to get some stat out of an eet file. + * eet filenames are now stringshare'd. + * increased eet_connection packet size to 1Mb. + * make eet tool write to stdout if no output file is given. + +Eet 1.5.0 + +Changes since Eet 1.4.0: +-------------------------- + +Additions: + + * EET_DATA_DESCRIPTOR_ADD_LIST_STRING API for string lists + * eet_node API's to manipulate nodes + * eet_alias_get API + * eet_data_xattr_cipher_get and eet_data_xattr_cipher_set APIs + * EET_DATA_DESCRIPTOR_ADD_BASIC_ARRAY API + +Fixes: + + * eet shutdown on windows + * test case to init eet + * compilation against libjpeg 8 on windows + * binary open on windows + * unopenable empty eet file for read/write + +Improvements: + + * better speed and memory footprint of EET_G_UNION and EET_G_ARRAY + * use stringshare for mmaped file names + * use eina locking wrappers + * use eina_file for file IO + * jpeg encode and decode quality improved at expense of speed diff --git a/README b/README new file mode 100644 index 0000000..989f4bb --- /dev/null +++ b/README @@ -0,0 +1,68 @@ +Eet 1.7.99 + +****************************************************************************** + + FOR ANY ISSUES PLEASE EMAIL: + enlightenment-devel@lists.sourceforge.net + +****************************************************************************** + +Requirements: +------------- +Must have: + libc + zlib + libjpeg + eina (1.1.0 or better) + (For windows you also need: evil) + +Optional requirements: + gnutls (1.7.6 or better) + openssl + +Eet is a tiny library designed to write an arbitrary set of chunks of +data to a file and optionally compress each chunk (very much like a +zip file) and allow fast random-access reading of the file later +on. It does not do zip as a zip itself has more complexity than is +needed, and it was much simpler to implement this once here. + +It also can encode and decode data structures in memory, as well as +image data for saving to eet files or sending across the network to +other machines, or just writing to arbitrary files on the system. All +data is encoded in a platform independent way and can be written and +read by any architecture. This data once encoded can be sent to +another process or machine and decoded on the other end without +needing to go into an eet file. Eet can also optionally encrypt files +and use digital signatures (with gnutls or openssl support). + +------------------------------------------------------------------------------ +COMPILING AND INSTALLING: + + ./configure + make +(do this as root unless you are installing in your users directories): + make install + +To get the coverage report: + make coverage +The report is created in the coverage/ subdir +If you want to be able to run coverage test over eet, you will need gcov +(usually any distro provides it) and lcov from: + http://ltp.sourceforge.net/coverage/lcov.php. +For coverage support you also need "make check" support with the check +library (see below). + +For compilation with MinGW, fnmatch.h is probably missing. That file can be +found here: + http://www.koders.com/c/fid2B518462CB1EED3D4E31E271DB83CD1582F6EEBE.aspx +It should be installed in the mingw include directory. + +For compilation with mingw32ce, run configure with the option + --host=arm-wince-mingw32ce + +For compilation with cegcc, follow the wiki: + http://wiki.enlightenment.org/index.php/Category:EFL_Windows_CE + +If you want to be able to run "make check", you need library check + from http://check.sourceforge.net/ + diff --git a/autogen.sh b/autogen.sh index 995ff2f..72e1033 100755 --- a/autogen.sh +++ b/autogen.sh @@ -3,7 +3,7 @@ rm -rf autom4te.cache rm -f aclocal.m4 ltmain.sh -touch README +touch ABOUT-NLS echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS -I m4 || exit 1 echo "Running autoheader..." ; autoheader || exit 1 @@ -11,6 +11,28 @@ echo "Running autoconf..." ; autoconf || exit 1 echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1 echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1 +W=0 + +rm -f config.cache-env.tmp +echo "OLD_PARM=\"$@\"" >> config.cache-env.tmp +echo "OLD_CFLAGS=\"$CFLAGS\"" >> config.cache-env.tmp +echo "OLD_PATH=\"$PATH\"" >> config.cache-env.tmp +echo "OLD_PKG_CONFIG_PATH=\"$PKG_CONFIG_PATH\"" >> config.cache-env.tmp +echo "OLD_LDFLAGS=\"$LDFLAGS\"" >> config.cache-env.tmp + +cmp config.cache-env.tmp config.cache-env >> /dev/null +if [ $? -ne 0 ]; then + W=1; +fi + +if [ $W -ne 0 ]; then + echo "Cleaning configure cache..."; + rm -f config.cache config.cache-env + mv config.cache-env.tmp config.cache-env +else + rm -f config.cache-env.tmp +fi + if [ -z "$NOCONFIGURE" ]; then - ./configure "$@" + ./configure -C "$@" fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..444b840 --- /dev/null +++ b/configure.ac @@ -0,0 +1,541 @@ +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +m4_define([v_maj], [1]) +m4_define([v_min], [7]) +m4_define([v_mic], [99]) +m4_define([v_rev], m4_esyscmd([(svnversion "${SVN_REPO_PATH:-.}" | grep -v '\(export\|Unversioned directory\)' || echo 0) | awk -F : '{printf("%s\n", $1);}' | tr -d ' :MSP\n'])) +m4_if(v_rev, [0], [m4_define([v_rev], m4_esyscmd([git log 2> /dev/null | (grep -m1 git-svn-id || echo 0) | sed -e 's/.*@\([0-9]*\).*/\1/' | tr -d '\n']))]) +##-- When released, remove the dnl on the below line +dnl m4_undefine([v_rev]) +##-- When doing snapshots - change soname. remove dnl on below line +dnl m4_define([relname], [ver-pre-svn-05]) +dnl m4_define([v_rel], [-release relname]) +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +m4_ifdef([v_rev], [m4_define([v_ver], [v_maj.v_min.v_mic.v_rev])], [m4_define([v_ver], [v_maj.v_min.v_mic])]) +m4_define([lt_cur], m4_eval(v_maj + v_min)) +m4_define([lt_rev], v_mic) +m4_define([lt_age], v_min) +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## + +AC_INIT([eet], [v_ver], [enlightenment-devel@lists.sourceforge.net]) +AC_PREREQ([2.52]) +AC_CONFIG_SRCDIR([configure.ac]) +AC_CONFIG_MACRO_DIR([m4]) + +AC_CONFIG_HEADERS([config.h]) +AH_TOP([ +#ifndef EFL_CONFIG_H__ +#define EFL_CONFIG_H__ +]) +AH_BOTTOM([ +#endif /* EFL_CONFIG_H__ */ +]) + +AM_INIT_AUTOMAKE([1.6 dist-bzip2]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +AC_GNU_SOURCE + +AC_LIBTOOL_WIN32_DLL +define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl +define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl +AC_PROG_LIBTOOL + +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +m4_ifdef([v_rev], , [m4_define([v_rev], [0])]) +m4_ifdef([v_rel], , [m4_define([v_rel], [])]) +AC_DEFINE_UNQUOTED(VMAJ, [v_maj], [Major version]) +AC_DEFINE_UNQUOTED(VMIN, [v_min], [Minor version]) +AC_DEFINE_UNQUOTED(VMIC, [v_mic], [Micro version]) +AC_DEFINE_UNQUOTED(VREV, [v_rev], [Revison]) +version_info="lt_cur:lt_rev:lt_age" +release_info="v_rel" +AC_SUBST(version_info) +AC_SUBST(release_info) +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## +VMAJ=v_maj +AC_SUBST(VMAJ) + + +### Needed information + +AC_CANONICAL_BUILD +AC_CANONICAL_HOST + +### Default options with respect to host + +requirements_pc_eet="" +requirements_libs_eet="" + +### Additional options to configure + +EFL_ENABLE_BIN([eet]) + +# Old eet file format support + +AC_ARG_ENABLE(old-eet-file-format, + [AC_HELP_STRING( + [--disable-old-eet-file-format], + [disable old eet file format support @<:@default=enabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + old_eet_file_format="yes" + else + old_eet_file_format="no" + fi + ], + [old_eet_file_format="yes"]) + +AC_MSG_CHECKING([whether to support old eet file format]) +AC_MSG_RESULT([${old_eet_file_format}]) + +if test "x${old_eet_file_format}" = "xyes" ; then + AC_DEFINE(EET_OLD_EET_FILE_FORMAT, 1, [support old eet file format]) +else + AC_DEFINE(EET_OLD_EET_FILE_FORMAT, 0, [support old eet file format]) +fi + +# Openssl support + +AC_ARG_ENABLE([openssl], + [AC_HELP_STRING([--disable-openssl], [disable openssl eet support @<:@default=auto@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + want_openssl="yes" + else + want_openssl="no" + fi + ], + [want_openssl="auto"]) + +AC_MSG_CHECKING([whether to use OpenSSL]) +AC_MSG_RESULT([${want_openssl}]) + +# Cryptography support + +AC_ARG_ENABLE([cipher], + [AC_HELP_STRING([--disable-cipher], [disable cipher support for eet API @<:@default=yes@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + want_cipher="yes" + else + want_cipher="no" + fi + ], + [want_cipher="yes"]) + +AC_MSG_CHECKING([whether to use cipher]) +AC_MSG_RESULT([${want_cipher}]) + +AC_ARG_ENABLE([signature], + [AC_HELP_STRING([--disable-signature], [disable signature file support for eet @<:@default=yes@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + want_signature="yes" + else + want_signature="no" + fi + ], + [want_signature="yes"]) + +AC_MSG_CHECKING([whether to use signature]) +AC_MSG_RESULT([${want_signature}]) + +# Assert or fail. + +AC_ARG_ENABLE([assert], + [AC_HELP_STRING([--enable-assert], [enable assert, @<:@default=no@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + prefer_assert="yes" + else + prefer_assert="no" + fi + ], + [prefer_assert="no"]) + +# Examples + +AC_ARG_ENABLE([install-examples], + [AC_HELP_STRING([--disable-install-examples], + [disable installing examples (compiled or just source). @<:@default=yes@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + install_examples="yes" + else + install_examples="no" + fi + ], + [install_examples="yes"]) + +AM_CONDITIONAL([INSTALL_EXAMPLES], [test "x${install_examples}" = "xyes"]) + +AC_ARG_ENABLE([build-examples], + [AC_HELP_STRING([--enable-build-examples], + [enable building examples @<:@default=yes@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + build_examples="yes" + else + build_examples="no" + fi + ], + [build_examples="no"]) +AM_CONDITIONAL([BUILD_EXAMPLES], [test "x${build_examples}" = "xyes"]) + + +### Checks for programs +AC_PROG_CC + +# pkg-config +PKG_PROG_PKG_CONFIG + +# Check whether pkg-config supports Requires.private +if $PKG_CONFIG --atleast-pkgconfig-version 0.22; then + pkgconfig_requires_private="Requires.private" +else + pkgconfig_requires_private="Requires" +fi +AC_SUBST(pkgconfig_requires_private) + + +# doxygen program for documentation building + +EFL_CHECK_DOXYGEN([build_doc="yes"], [build_doc="no"]) + +### Checks for libraries + +## Compatibility layers + +# Evil library for compilation on Windows + +EFL_EET_BUILD="" +case "$host_os" in + mingw*) + PKG_CHECK_EXISTS([evil >= 1.1.0]) + AC_DEFINE([HAVE_EVIL], [1], [Set to 1 if Evil package is installed]) + requirements_pc_eet="evil ${requirements_pc_eet}" + EFL_EET_BUILD="-DEFL_EET_BUILD" + ;; +esac +AC_SUBST(EFL_EET_BUILD) + +# Exotic library for copilation on Coyote + +PKG_CHECK_EXISTS([exotic], + [ + enable_exotic="yes" + AC_DEFINE([HAVE_EXOTIC_H], [1], [Define to 1 if you have Exotic.]) + requirements_pc_eet="exotic ${requirements_pc_eet}" + ], + [enable_exotic="no"]) + +## Secure layer + +# Gnutls library + +AC_ARG_ENABLE([gnutls], + [AC_HELP_STRING([--disable-gnutls], [disable gnutls eet support @<:@default=auto@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + want_gnutls="yes" + else + want_gnutls="no" + fi + ], + [want_gnutls="auto"]) + +AC_MSG_CHECKING([whether to use Gnutls]) +AC_MSG_RESULT([${want_gnutls}]) + +have_gnutls="no" +if test "x${want_gnutls}" = "xyes" || test "x${want_gnutls}" = "xauto" ; then + PKG_CHECK_MODULES([GNUTLS], [gnutls >= 1.7.6], + [ + have_gnutls="yes" + want_openssl="no" + AC_DEFINE([HAVE_GNUTLS], [1], [Have Gnutls support]) + requirements_pc_eet="gnutls >= 1.7.6 ${requirements_pc_eet}" + ], + [have_gnutls="no"]) +fi + +# libgcrypt + +if test "x${have_gnutls}" = "xyes" ; then + AC_PATH_GENERIC([libgcrypt], [], [have_gnutls="yes"], [have_gnutls="no"]) + if test "x${have_gnutls}" = "xyes" ; then + requirements_libs_eet="${LIBGCRYPT_LIBS} ${requirements_libs_eet}" + fi +fi + +# Specific GNUTLS improvement + +AC_ARG_ENABLE(new-gnutls-api, + [AC_HELP_STRING( + [--disable-new-gnutls-api], + [enable use of gnutls_x509_crt_verify_hash. @<:@default=yes@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + new_gnutls_api="yes" + else + new_gnutls_api="no" + fi + ], + [new_gnutls_api="yes"]) + +AC_MSG_CHECKING([whether to use gnutls_x509_crt_verify_hash]) +AC_MSG_RESULT([${new_gnutls_api}]) + +if test "x${have_gnutls}" = "xyes" && test "x${new_gnutls_api}" = "xyes" ; then + CFLAGS_save="${CFLAGS}" + LIBS_save="${LIBS}" + CFLAGS="${GNUTLS_CFLAGS}" + LIBS="${GNUTLS_LIBS}" + AC_CHECK_LIB([gnutls], [gnutls_x509_crt_verify_hash], + [ + AC_DEFINE([EET_USE_NEW_GNUTLS_API], [1], [use gnutls_x509_crt_verify_hash]) + new_gnutls_api="yes" + ], + [new_gnutls_api="no"]) + CFLAGS="${CFLAGS_save}" + LIBS="${LIBS_save}" +fi + +use_gnutls_privkey_sign_data="no" +if test "x${have_gnutls}" = "xyes" ; then + CFLAGS_save="${CFLAGS}" + LIBS_save="${LIBS}" + CFLAGS="${GNUTLS_CFLAGS}" + LIBS="${GNUTLS_LIBS}" + AC_CHECK_LIB([gnutls], [gnutls_privkey_sign_data], + [ + AC_DEFINE([EET_USE_NEW_PRIVKEY_SIGN_DATA], [1], [use gnutls_privkey_sign_data]) + use_gnutls_privkey_sign_data="yes" + ], + [use_gnutls_privkey_sign_data="no"]) + CFLAGS="${CFLAGS_save}" + LIBS="${LIBS_save}" +fi + +AC_MSG_CHECKING([whether to use gnutls_privkey_sign_data]) +AC_MSG_RESULT([${use_gnutls_privkey_sign_data}]) + +use_gnutls_pubkey_verify_hash="no" +if test "x${have_gnutls}" = "xyes" ; then + CFLAGS_save="${CFLAGS}" + LIBS_save="${LIBS}" + CFLAGS="${GNUTLS_CFLAGS}" + LIBS="${GNUTLS_LIBS}" + AC_CHECK_LIB([gnutls], [gnutls_pubkey_verify_hash], + [ + AC_DEFINE([EET_USE_NEW_PUBKEY_VERIFY_HASH], [1], [use gnutls_pubkey_verify_hash]) + use_gnutls_pubkey_verify_hash="yes" + ], + [use_gnutls_pubkey_verify_hash="no"]) + CFLAGS="${CFLAGS_save}" + LIBS="${LIBS_save}" +fi + +AC_MSG_CHECKING([whether to use gnutls_pubkey_verify_hash]) +AC_MSG_RESULT([${use_gnutls_pubkey_verify_hash}]) + +# Openssl library +have_openssl="no" +if test "x${want_openssl}" = "xyes" || test "x${want_openssl}" = "xauto" ; then + PKG_CHECK_EXISTS([openssl], + [ + have_openssl="yes" + AC_DEFINE([HAVE_OPENSSL], [1], [Have Openssl support]) + requirements_pc_eet="openssl ${requirements_pc_eet}" + ], + [have_openssl="no"]) +fi + +if test "x${have_gnutls}" = "xyes" ; then + secure_layer="GnuTLS" +elif test "x${have_openssl}" = "xyes" ; then + secure_layer="OpenSSL" +else + secure_layer="no" +fi + +have_cipher="no" +if test "x${have_gnutls}" = "xyes" && test "x${want_cipher}" = "xyes" ; then + have_cipher="yes" + AC_DEFINE([HAVE_CIPHER], [1], [Have cipher support built in eet]) +elif test "x${have_openssl}" = "xyes" && test "x${want_cipher}" = "xyes" ; then + have_cipher="yes" + AC_DEFINE([HAVE_CIPHER], [1], [Have cipher support built in eet]) +fi + +AC_MSG_CHECKING([whether to activate cipher support in eet]) +AC_MSG_RESULT([${have_cipher}]) + +have_signature="no" +if test "x${have_gnutls}" = "xyes" && test "x${want_signature}" = "xyes" ; then + have_signature="yes" + AC_DEFINE([HAVE_SIGNATURE], [1], [Have signature support for eet file]) +elif test "x${have_openssl}" = "xyes" && test "x${want_signature}" = "xyes" ; then + have_signature="yes" + AC_DEFINE([HAVE_SIGNATURE], [1], [Have signature support for eet file]) +fi + +AC_MSG_CHECKING([whether to activate signature support in eet]) +AC_MSG_RESULT([${have_signature}]) + +# libjpeg and zlib +EFL_CHECK_LIBS([eet], [libjpeg zlib]) + +# Eina library + +requirements_pc_eet="eina >= 1.2.0 ${requirements_pc_eet}" +PKG_CHECK_MODULES([EET], [${requirements_pc_eet}]) + +case "$host_os" in + mingw32ce*) + requirements_libs_eet="${requirements_libs_eet} -lws2" + ;; + mingw*) + requirements_libs_eet="${requirements_libs_eet} -lws2_32" + ;; +esac + +EET_LIBS="${EET_LIBS} ${requirements_libs_eet}" + + +### Checks for header files + +AC_CHECK_HEADERS(netinet/in.h unistd.h) +EFL_CHECK_PATH_MAX + +### Checks for types + + +### Checks for structures + + +### Checks for compiler characteristics +AM_PROG_CC_C_O +AC_C_INLINE +AC_PROG_CC_STDC +AC_C___ATTRIBUTE__ + +# Check whether the null pointer is zero on this arch +AC_TRY_RUN( + [ +#include +#include +int main (int argc, char **argv) { + void *foo = NULL; + uintptr_t bar = (uintptr_t)foo; + return (uintptr_t)foo; +} + ], + [have_null="yes"], + [have_null="no"], + [ + AC_MSG_WARN([Cannot check when cross-compiling -- assuming null is okay]) + have_null="yes" + ]) +AC_MSG_CHECKING([value of the null pointer]) +AC_MSG_RESULT([${have_null}]) + +if test ! "x${have_null}" = "xyes" ; then + AC_MSG_WARN([Your system is a bit too funny, eet might not work properly]) +fi + + +### Checks for linker characteristics + +# use --enable-auto-import on Windows + +lt_enable_auto_import="" +case "$host_os" in + mingw*) + lt_enable_auto_import="-Wl,--enable-auto-import" + ;; +esac +AC_SUBST([lt_enable_auto_import]) + +case "${host_os}" in + openbsd*) + ;; + *) + EFL_LINKER_FLAG([-Wl,--as-needed]) + ;; +esac + + +### Checks for library functions +AC_ISC_POSIX +AC_FUNC_ALLOCA + +EFL_CHECK_FUNCS([eet], [fnmatch]) + + +### Unit tests, coverage and benchmarking + +EFL_CHECK_TESTS([eet], [enable_tests="yes"], [enable_tests="no"]) + + +AC_SUBST([requirements_pc_eet]) +AC_SUBST([requirements_libs_eet]) + +AC_OUTPUT([ +Makefile +eet.pc +doc/Makefile +doc/Doxyfile +doc/eet.dox +src/Makefile +src/lib/Makefile +src/bin/Makefile +src/tests/Makefile +src/examples/Makefile +eet.spec +]) + + +##################################################################### +## Info + +echo +echo +echo +echo "------------------------------------------------------------------------" +echo "$PACKAGE_NAME $PACKAGE_VERSION" +echo "------------------------------------------------------------------------" +echo +echo "Configuration Options Summary:" +echo +echo " Secure layer.........: ${secure_layer}" +if test "x${have_gnutls}" = "xyes" || test "x${have_openssl}" = "xyes" ; then + echo " Cipher support.....: ${have_cipher}" + echo " Signature..........: ${have_signature}" +fi +echo +echo " Old eet file format..: ${old_eet_file_format}" +echo +echo " Tests................: ${enable_tests} (Coverage: ${efl_enable_coverage})" +echo +echo " Build eet............: $have_eet" +echo +echo " Documentation........: ${build_doc}" +if test "x${build_doc}" = "xyes" ; then + echo " Building...........: make doc" +fi +echo " Examples.............: ${build_examples}" +echo " Examples installed...: ${install_examples}" +echo +echo "Compilation............: make (or gmake)" +echo " CPPFLAGS.............: $CPPFLAGS" +echo " CFLAGS...............: $CFLAGS" +echo " LDFLAGS..............: $LDFLAGS" +echo +echo "Installation...........: make install (as root if needed, with 'su' or 'sudo')" +echo " prefix...............: $prefix" +echo diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..4421a3d --- /dev/null +++ b/debian/changelog @@ -0,0 +1,460 @@ +eet (1.6.0+svn.70375slp2+build02) unstable; urgency=low + + * Package Upload + * Git: slp/pkgs/e/eet + * Tag: eet_1.6.0+svn.70375slp2+build02 + + -- Myungjae Lee Wed, 25 Apr 2012 17:28:05 +0900 + +eet (1.6.0+svn.70375slp2+build01) unstable; urgency=low + + * Package Upload + * Git: slp/pkgs/e/eet + * Tag: eet_1.6.0+svn.70375slp2+build01 + + -- Myungjae Lee Wed, 25 Apr 2012 15:12:39 +0900 + +eet (1.6.0+svn.70308slp2+build01) unstable; urgency=low + + * Package Upload + * Git: slp/pkgs/e/eet + * Tag: eet_1.6.0+svn.70308slp2+build01 + + -- Jaehwan Kim Mon, 23 Apr 2012 15:28:18 +0900 + +eet (1.6.0+svn.70142slp2+build01) unstable; urgency=low + + * Package Upload + * Git: slp/pkgs/e/eet + * Tag: eet_1.6.0+svn.70142slp2+build01 + + -- Jiyoun Park Fri, 13 Apr 2012 18:31:30 +0900 + +eet (1.6.0+svn.69899slp2+build01) unstable; urgency=low + + * Package Upload + * Git: slp/pkgs/e/eet + * Tag: eet_1.6.0+svn.69899slp2+build01 + + -- Jeonghyun Yun Fri, 06 Apr 2012 18:11:00 +0900 + +eet (1.5.0+svn.69626slp2+build01) unstable; urgency=low + + * Package Upload + * Git: slp/pkgs/e/eet + * Tag: eet_1.5.0+svn.69626slp2+build01 + + -- Jeonghyun Yun Wed, 28 Mar 2012 14:27:55 +0900 + +eet (1.5.0+svn.68718slp2+build01) unstable; urgency=low + + * Package Upload + * Git: slp/pkgs/e/eet + * Tag: eet_1.5.0+svn.68718slp2+build01 + + -- Jeonghyun Yun Wed, 07 Mar 2012 16:43:31 +0900 + +eet (1.5.0+svn.68521slp2+build01) unstable; urgency=low + + * Package upload + * Git: slp/pkgs/e/eet + * Tag: eet_1.5.0+svn.68521slp2+build01 + + -- Jeonghyun Yun Fri, 02 Mar 2012 06:30:44 -0500 + +eet (1.5.0+svn.67705slp2+build01) unstable; urgency=low + + * Package Upload + * Git: slp/pkgs/e/eet + * Tag: eet_1.5.0+svn.67705slp2+build01 + + -- Jaehwan Kim Wed, 15 Feb 2012 18:59:11 +0900 + +eet (1.5.0+svn.66958slp2+build01) unstable; urgency=low + + * Package Upload + * Git: slp/pkgs/e/eet + * Tag: eet_1.5.0+svn.66958slp2+build01 + + -- Jaehwan Kim Mon, 16 Jan 2012 18:28:56 +0900 + +eet (1.5.0+svn.65860slp2+build02) unstable; urgency=low + + * libjpeg7 -> libjpeg8 + * Git: slp/pkgs/e/eet + * Tag: eet_1.5.0+svn.65860slp2+build02 + + -- ChunEon Park Wed, 11 Jan 2012 14:08:18 +0900 + +eet (1.5.0+svn.65860slp2+build01) unstable; urgency=low + + * Package Upload for migration + * Git: slp-scm.sec.samsung.net:slp/pkgs/e/eet + * Tag: eet_1.5.0+svn.65860slp2+build01 + + -- Jaehwan Kim Thu, 08 Dec 2011 13:48:37 +0900 + +eet (1.5.0+svn.65577slp2+build01) unstable; urgency=low + + * Package Upload + * Git: slp-scm.sec.samsung.net:slp/pkgs/e/eet + * Tag: eet_1.5.0+svn.65577slp2+build01 + + -- Jaehwan Kim Tue, 29 Nov 2011 13:29:42 +0900 + +eet (1.5.0+svn.65300slp2+build01) unstable; urgency=low + + * Merge with upstream @65300 + + -- Mike McCormack Thu, 17 Nov 2011 08:20:00 +0900 + +eet (1.2.0+svn.64981slp2+build01) unstable; urgency=low + + * Merge with upstream @64981 + + -- Mike McCormack Thu, 10 Nov 2011 11:29:43 +0900 + +eet (1.2.0+svn.64494slp2+build01) unstable; urgency=low + + * Merge with upstream 64494 + + -- Mike McCormack Thu, 03 Nov 2011 09:33:23 +0900 + +eet (1.2.0+svn.63811slp2+build01) unstable; urgency=low + + * Merge with upstream + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.63811slp2+build01 + + -- Mike McCormack Wed, 05 Oct 2011 11:33:08 +0900 + +eet (1.2.0+svn.62590slp2+build01) unstable; urgency=low + + * [SVN EFL Migration] eet in SLP is merged with SVN r62590 + * Important Changes + [Migration upstream r62590] Merge remote branch 'origin/upstream' into svn_merge + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.62590slp2+build01 + + -- Jaehwan Kim Fri, 02 Sep 2011 18:41:10 +0900 + +eet (1.2.0+svn.60246slp2+build01) unstable; urgency=low + + * [SVN EFL Migration] eet in SLP is merged with SVN r60246 + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.60246slp2+build01 + + -- Jaehwan Kim Fri, 24 Jun 2011 18:09:42 +0900 + +eet (1.2.0+svn.58117slp2+build01) unstable; urgency=low + + * [SVN EFL Migration] eet in SLP is merged with SVN r58117 + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.58117slp2+build01 + + -- Jaehwan Kim Tue, 05 Apr 2011 15:54:48 +0900 + +eet (1.2.0+svn.57844slp2+build02) unstable; urgency=low + + * Rollback + * Git: slp-scm.sec.samsung.net:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.57844slp2+build02 + + -- Shinwoo Kim Tue, 29 Mar 2011 23:30:25 +0900 + +eet (1.2.0+svn.57844slp2+build01) unstable; urgency=low + + * [SVN EFL Migration] eet in SLP is merged with SVN r57844 + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.57844slp2+build01 + + -- Shinwoo Kim Tue, 29 Mar 2011 18:55:12 +0900 + +eet (1.2.0+svn.57246slp2+build05) unstable; urgency=low + + * [SVN EFL Migration] eet in SLP is merged with SVN r57246 + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.57246slp2+build05 + + -- Myungjae Lee Wed, 09 Mar 2011 11:29:22 +0900 + +eet (1.2.0+svn.57246slp2+build04) unstable; urgency=low + + * [SVN EFL Migration] eet in SLP is merged with SVN r57246 + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.57246slp2+build04 + + -- Myungjae Lee Wed, 09 Mar 2011 11:14:38 +0900 + +eet (1.2.0+svn.57246slp2+build03) unstable; urgency=low + + * Package Upload : Rollback + * Git: 165.213.180.234:/slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.57246slp2+build03 + + -- WooHyun Jung Tue, 08 Mar 2011 12:10:46 +0900 + +eet (1.2.0+svn.57246slp2+build02) unstable; urgency=low + + * Package upload : Rollback + * Git: 165.213.180.234:/slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.57246slp2+build02 + + -- WooHyun Jung Tue, 08 Mar 2011 11:02:33 +0900 + +eet (1.2.0+svn.57246slp2+build01) unstable; urgency=low + + * [SVN EFL Migration] eet in SLP is merged with SVN r57246 + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.57246slp2+build01 + + -- Myungjae Lee Mon, 07 Mar 2011 17:27:55 +0900 + +eet (1.2.0+svn.56194slp2+build02) unstable; urgency=low + + * [SVN EFL Migration] eet in SLP is merged with SVN r56194 + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.56194slp2+build02 + + -- WooHyun Jung Thu, 27 Jan 2011 12:20:29 +0900 + +eet (1.2.0+svn.56194slp2+build01) unstable; urgency=low + + * [SVN EFL Migration] eet in SLP is merged with SVN r56194 + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.56194slp2+build01 + + -- WooHyun Jung Wed, 26 Jan 2011 13:21:31 +0900 + +eet (1.2.0+svn.55981slp2+build01) unstable; urgency=low + + * [SVN EFL Migration] eet in SLP is merged with SVN r55981 + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.55981slp2+build01 + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.55981slp2+build01 + + -- WooHyun Jung Wed, 19 Jan 2011 16:13:48 +0900 + +eet (1.2.0+svn.55636slp2+build01) unstable; urgency=low + + * Package Upload + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.55636slp2+build01 + + -- Jaehwan Kim Mon, 03 Jan 2011 20:56:30 +0900 + +eet (1.2.0+svn.55490slp2+build01) unstable; urgency=low + + * [SVN EFL Migration] eet in SLP is merged with SVN r55490 + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.55490slp2+build01 + + -- Jaehwan Kim Wed, 22 Dec 2010 19:54:50 +0900 + +eet (1.2.0+svn.55432slp2+build01) unstable; urgency=low + + * [SVN's EFL Migration] eet in SLP is merged with SVN r55432. + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.55432slp2+build01 + + -- Juyung Seo Tue, 14 Dec 2010 17:30:12 +0900 + +eet (1.2.0+svn.55070slp2+build04) unstable; urgency=low + + * [SVN's EFL Migration] eet in SLP is merged with SVN r55432. + * Git: 165.213.180.234:slp/pkgs/e/eet + * Tag: eet_1.2.0+svn.55070slp2+build04 + + -- Juyung Seo Tue, 14 Dec 2010 14:47:53 +0900 + +eet (1.2.0+svn.55070slp2+build03) unstable; urgency=low + + * [SVN 55070 Merge] + * Update to SVN Revision 55070. + * Git: 165.213.180.234:/git/slp/pkgs/eet + * Tag: eet_1.2.0+svn.55070slp2+build03 + + -- Myoungwoon Kim Thu, 02 Dec 2010 14:12:02 +0900 + +eet (1.2.0+svn.55070slp2+build02) unstable; urgency=low + + * Rollback to eet_1.2.0+svn.51480slp2+build03. + * Git: 165.213.180.234:/git/slp/pkgs/eet + * Tag: eet_1.2.0+svn.55070slp2+build02 + + -- Juyung Seo Thu, 02 Dec 2010 09:41:29 +0900 + +eet (1.2.0+svn.55070slp2+build01) unstable; urgency=low + + * [SVN 55070 Merge] + * Update to SVN Revision 55070. + * Git: 165.213.180.234:/git/slp/pkgs/eet + * Tag: eet_1.2.0+svn.55070slp2+build01 + + -- Myoungwoon Kim Thu, 02 Dec 2010 08:59:59 +0900 + +eet (1.2.0+svn.51480slp2+build03) unstable; urgency=low + + * [SVN 54765 Merge] + * Update to SVN Revision 54765. + * Git: 165.213.180.234:/git/slp/pkgs/eet + * Tag: eet_1.2.0+svn.51480slp2+build03 + + -- Juyung Seo Fri, 26 Nov 2010 15:10:46 +0900 + +eet (1.2.0+svn.51480slp2+build02) unstable; urgency=low + + * add as-needed + * Git: 165.213.180.234:/git/slp/pkgs/eet + * Tag: eet_1.2.0+svn.51480slp2+build02 + + -- Jaehwan.kim Wed, 15 Sep 2010 09:34:32 +0900 + +eet (1.2.0+svn.51480slp2+build01) unstable; urgency=low + + * efl 1.0 alpha upgradey + * Git: 165.213.180.234:/git/slp/pkgs/eet + * Tag: eet_1.2.0+svn.51480slp2+build01 + + -- Jaehwan.kim Tue, 31 Aug 2010 22:39:25 +0900 + +eet (1.2.0+svn.49540slp2+3build04) unstable; urgency=low + + * Packaging. + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/EFL-pkgs/eet + * Tag: eet_1.2.0+svn.49540slp2+3build04 + + -- Daniel Juyung Seo Thu, 10 Jun 2010 21:09:31 +0900 + +eet (1.2.0+svn.49540slp2+3build03) unstable; urgency=low + + * Packaging. + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/EFL-pkgs/eet + * Tag: eet_1.2.0+svn.49540slp2+3build03 + + -- Daniel Juyung Seo Thu, 10 Jun 2010 21:04:14 +0900 + +eet (1.2.0+svn.49540slp2+3build02) unstable; urgency=low + + * Packaging. + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/EFL-pkgs/eet + * Tag: eet_1.2.0+svn.49540slp2+3build02 + + -- Daniel Juyung Seo 목, 10 6월 2010 21:00:51 +0900 + +eet (1.2.0+svn.49540slp2+3) unstable; urgency=low + + * Packaging. + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/EFL-pkgs/eet + * Tag: eet_1.2.0+svn.49540slp2+3 + + -- Daniel Juyung Seo Thu, 10 Jun 2010 20:46:54 +0900 + +eet (1.2.0+svn.49540slp2+2) unstable; urgency=low + + * Packaging. + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/EFL-pkgs/eet + * Tag: eet_1.2.0+svn.49540slp2+2 + + -- Daniel Juyung Seo Thu, 10 Jun 2010 20:39:03 +0900 + +eet (1.2.0+svn.49540slp2+1) unstable; urgency=low + + * Packaging. + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/EFL-pkgs/eet + * Tag: eet_1.2.0+svn.49540slp2+1 + + -- Daniel Juyung Seo Thu, 10 Jun 2010 20:13:45 +0900 + +eet (1.2.0+svn.49540slp2+0) unstable; urgency=low + + * Update opensource EFL from SVN + * SVN revision: 49540 (Total EFL revision: 49550) + * Tag: 1.2.0+svn.49540slp2+0 + + -- Daniel Juyung Seo Thu, 10 Jun 2010 15:50:39 +0900 + +eet (1.2.0+svn20100304slp2) unstable; urgency=low + + * change package version + + -- Jaehwan Kim Thu, 25 Mar 2010 15:56:23 +0900 + +eet (1.2.0+svn20100304-1) unstable; urgency=low + + * EFL_update_revision_46864 + + -- Jaehwan Kim Wed, 10 Mar 2010 16:06:33 +0900 + +eet (1.2.0+svn20100203-2) unstable; urgency=low + + * repack + + -- Jaehwan Kim Thu, 04 Feb 2010 20:21:09 +0900 + +eet (1.2.0+svn20100203-1) unstable; urgency=low + + * EFL_update_revision_45828 + + -- Jaehwan Kim Wed, 03 Feb 2010 16:39:18 +0900 + +eet (1.2.0+svn20100119-2) unstable; urgency=low + + * After cleaning, upload + + -- Jihoon Kim Fri, 22 Jan 2010 02:02:34 +0900 + +eet (1.2.0+svn20100119-1) unstable; urgency=low + + * EFL_update_revision_45322 + + -- Jihoon Kim Tue, 19 Jan 2010 20:44:46 +0900 + +eet (1.2.0+svn20100111-3) unstable; urgency=low + + * reupload EFL i686 + + -- Jaehwan Kim Tue, 12 Jan 2010 17:35:23 +0900 + +eet (1.2.0+svn20100111-2) unstable; urgency=low + + * reupload EFL + + -- Jaehwan Kim Mon, 11 Jan 2010 22:16:25 +0900 + +eet (1.2.0+svn20100111-1) unstable; urgency=low + + * update EFL revision 45026 + + -- Jaehwan Kim Mon, 11 Jan 2010 13:28:02 +0900 + +eet (1.2.0+svn20091229-1) unstable; urgency=low + + * update EFL + + -- Jaehwan Kim Tue, 29 Dec 2009 14:27:01 +0900 + +eet (1.2.0+svn20091112-4) unstable; urgency=low + + * modified control file : changed Architecture all to any (by Juyung Seo) + + -- sangho.g.park Fri, 27 Nov 2009 15:36:30 +0900 + +eet (1.2.0+svn20091112-3) unstable; urgency=low + + * svn stable version + + -- sangho.g.park Thu, 19 Nov 2009 17:32:45 +0900 + +eet (1.2.0+svn20091112-2) unstable; urgency=low + + * jpeg62 -> jpeg7 + + -- sangho.g.park Thu, 12 Nov 2009 16:45:00 +0100 + +eet (1.2.0+svnYYYYMMDD-1) unstable; urgency=low + + * Clean up changelog + + -- quaker Tue, 21 Apr 2009 19:13:08 +0100 diff --git a/debian/compat b/debian/compat index 1e8b314..7ed6ff8 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -6 +5 diff --git a/debian/control b/debian/control index 8e7f9d8..f52a88a 100644 --- a/debian/control +++ b/debian/control @@ -1,15 +1,16 @@ Source: eet Section: libs Priority: optional -Maintainer: Falko Schmidt -Build-Depends: debhelper (>= 6), cdbs, automake1.7 | automaken, libtool, pkg-config, zlib1g-dev, libjpeg62-dev, doxygen -Standards-Version: 3.7.3 +Maintainer: Jaehwan Kim , Juyung Seo , Jeonghyun Yun , Myoungwoon Kim , Mike McCormack , ChunEon Park +Build-Depends: dpkg-dev , debhelper (>= 6), cdbs, zlib1g-dev, libjpeg8-dev, pkg-config, libtool, libeina-dev, doxygen +Standards-Version: 3.8.1 Homepage: http://www.enlightenment.org Package: libeet-dev Section: libdevel Architecture: any -Depends: libeet1 (= ${Source-Version}), zlib1g-dev, libjpeg-dev +Depends: libeet1 (= ${binary:Version}), libjpeg8-dev, pkg-config +Recommends: libeet-doc Description: Enlightenment DR17 file chunk reading/writing library development files Eet is a tiny library designed to write an arbitary set of chunks of data to a file and optionally compress each chunk (very much like a zip file) and allow @@ -18,7 +19,6 @@ Description: Enlightenment DR17 file chunk reading/writing library development f this once here. . This package contains headers and static libraries for development with libeet. - libeet. Package: libeet-doc Section: doc diff --git a/debian/copyright b/debian/copyright index 7dc25b6..e97e5c3 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,41 +1,36 @@ -This package was debianized by Falko Schmidt on -Fri, 4 Apr 2008 12:23:41 +0000. +This package was debianized by Debian Pkg-e Team +Sat, 07 Jul 2007 09:29:10 +0000. -The source is downloaded from the e17/libs/eet module of the enlightenment CVS -tree. For more information, see: +It was downloaded from http://download.enlightenment.org/snapshots/LATEST/ - http://www.enlightenment.org +Upstream Authors: -Upstream Authors: Enlightenment team + Enlightenment team Copyright: - Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS) + Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS) License: - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to - deal in the Software without restriction, including without limitation the - rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - sell copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + The above copyright notice and this permission notice shall be included in - all copies of the Software, its documentation and marketing & publicity - materials, and acknowledgment shall be given in the documentation, materials - and software packages that this Software was used. - + all copies of the Software, its documentation and marketing & publicity + materials, and acknowledgment shall be given in the documentation, + materials and software packages that this Software was used. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. On Debian systems, the complete text of the BSD License can be found in `/usr/share/common-licenses/BSD'. - -The Debian packaging is: - (C) 2006 2007,Debian Pkg-e Team - and is licensed under the GPL, see `/usr/share/common-licenses/GPL'. diff --git a/debian/jobs b/debian/jobs new file mode 100644 index 0000000..e69de29 diff --git a/debian/libeet-dev.install b/debian/libeet-dev.install index 4a70bfa..73de9a8 100644 --- a/debian/libeet-dev.install +++ b/debian/libeet-dev.install @@ -1,4 +1,5 @@ debian/tmp/usr/lib/pkgconfig/* debian/tmp/usr/include/* debian/tmp/usr/lib/lib*.a +debian/tmp/usr/lib/lib*.la debian/tmp/usr/lib/lib*.so diff --git a/debian/libeet1.symbols b/debian/libeet1.symbols new file mode 100644 index 0000000..9a96c7c --- /dev/null +++ b/debian/libeet1.symbols @@ -0,0 +1,85 @@ +libeet.so.1 libeet1 #MINVER# + eet_clearcache@Base 1.0.0 + eet_close@Base 1.0.0 + eet_data_descriptor2_new@Base 1.0.0 + eet_data_descriptor3_new@Base 1.0.0 + eet_data_descriptor_decode@Base 1.0.0 + eet_data_descriptor_decode_cipher@Base 1.2.2 + eet_data_descriptor_element_add@Base 1.0.0 + eet_data_descriptor_encode@Base 1.0.0 + eet_data_descriptor_encode_cipher@Base 1.2.2 + eet_data_descriptor_free@Base 1.0.0 + eet_data_descriptor_new@Base 1.0.0 + eet_data_dump@Base 1.0.0 + eet_data_dump_cipher@Base 1.2.2 + eet_data_image_decode@Base 1.0.0 + eet_data_image_decode_cipher@Base 1.2.2 + eet_data_image_decode_to_surface@Base 1.1.0 + eet_data_image_decode_to_surface_cipher@Base 1.2.2 + eet_data_image_encode@Base 1.0.0 + eet_data_image_encode_cipher@Base 1.2.2 + eet_data_image_header_decode@Base 1.0.0 + eet_data_image_header_decode_cipher@Base 1.2.2 + eet_data_image_header_read@Base 1.0.0 + eet_data_image_header_read_cipher@Base 1.2.2 + eet_data_image_read@Base 1.0.0 + eet_data_image_read_cipher@Base 1.2.2 + eet_data_image_read_to_surface@Base 1.1.0 + eet_data_image_read_to_surface_cipher@Base 1.2.2 + eet_data_image_write@Base 1.0.0 + eet_data_image_write_cipher@Base 1.2.2 + eet_data_node_encode_cipher@Base 1.2.2 + eet_data_node_write_cipher@Base 1.2.2 + eet_data_read@Base 1.0.0 + eet_data_read_cipher@Base 1.2.2 + eet_data_text_dump@Base 1.0.0 + eet_data_text_dump_cipher@Base 1.2.2 + eet_data_text_undump@Base 1.0.0 + eet_data_text_undump_cipher@Base 1.2.2 + eet_data_undump@Base 1.0.0 + eet_data_undump_cipher@Base 1.2.2 + eet_data_write@Base 1.0.0 + eet_data_write_cipher@Base 1.2.2 + eet_delete@Base 1.0.0 + eet_dictionary_get@Base 1.0.0 + eet_dictionary_string_check@Base 1.0.0 + eet_identity_certificate_print@Base 1.1.0 + eet_identity_close@Base 1.1.0 + eet_identity_open@Base 1.1.0 + eet_identity_print@Base 1.1.0 + eet_identity_set@Base 1.1.0 + eet_identity_sha1@Base 1.2.2 + eet_identity_signature@Base 1.2.2 + eet_identity_x509@Base 1.1.0 + eet_init@Base 1.0.0 + eet_list@Base 1.0.0 + eet_memopen_read@Base 1.1.0 + eet_mode_get@Base 1.0.0 + eet_node_array_new@Base 1.2.2 + eet_node_char_new@Base 1.2.2 + eet_node_del@Base 1.2.2 + eet_node_double_new@Base 1.2.2 + eet_node_float_new@Base 1.2.2 + eet_node_hash_new@Base 1.2.2 + eet_node_inlined_string_new@Base 1.2.2 + eet_node_int_new@Base 1.2.2 + eet_node_list_new@Base 1.2.2 + eet_node_long_long_new@Base 1.2.2 + eet_node_null_new@Base 1.2.2 + eet_node_short_new@Base 1.2.2 + eet_node_string_new@Base 1.2.2 + eet_node_struct_child_new@Base 1.2.2 + eet_node_struct_new@Base 1.2.2 + eet_node_unsigned_char_new@Base 1.2.2 + eet_node_unsigned_int_new@Base 1.2.2 + eet_node_unsigned_long_long_new@Base 1.2.2 + eet_node_unsigned_short_new@Base 1.2.2 + eet_node_var_array_new@Base 1.2.2 + eet_num_entries@Base 1.0.0 + eet_open@Base 1.0.0 + eet_read@Base 1.0.0 + eet_read_cipher@Base 1.2.2 + eet_read_direct@Base 1.0.0 + eet_shutdown@Base 1.0.0 + eet_write@Base 1.0.0 + eet_write_cipher@Base 1.2.2 diff --git a/debian/rules b/debian/rules old mode 100644 new mode 100755 index 3833157..50da389 --- a/debian/rules +++ b/debian/rules @@ -3,20 +3,22 @@ include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/autotools.mk -DEB_INSTALL_MANPAGES_libeet-doc := $(DEB_SRCDIR)/doc/man/man3/*.3 -DEB_INSTALL_MANPAGES_libeet-bin := $(DEB_SRCDIR)/debian/eet.1 +CFLAGS += -fvisibility=hidden -fPIC +LDFLAGS += -fvisibility=hidden -Wl,--hash-style=both -Wl,--as-needed + + +#DEB_INSTALL_MANPAGES_libeet-doc := $(DEB_SRCDIR)/doc/man/man3/E*.3 +#DEB_INSTALL_MANPAGES_libeet-bin := $(DEB_SRCDIR)/debian/eet.1 DEB_DH_STRIP_ARGS := --dbg-package=libeet-dbg -DEB_CONFIGURE_EXTRA_FLAGS := --disable-rpath -DEB_MAKE_CLEAN_TARGET := clean +DEB_CONFIGURE_EXTRA_FLAGS := --disable-openssl --disable-cypher --disable-signature --disable-gnutls --disable-doc +DEB_CONFIGURE_SCRIPT := ./autogen.sh +DEB_MAKE_CLEAN_TARGET := distclean -build/libeet-doc:: - cd $(DEB_SRCDIR) && ./gendoc +#build/libeet-doc:: +# make doc -install/libeet-doc:: - cp -R $(DEB_SRCDIR)/doc/html debian/libeet-doc/usr/share/doc/libeet-doc/ - rm $(DEB_SRCDIR)/doc/man/man3/todo.3 +#install/libeet-doc:: +# cp -R $(DEB_SRCDIR)/doc/html debian/libeet-doc/usr/share/doc/libeet-doc/ clean:: - rm -rf $(DEB_SRCDIR)/doc/html $(DEB_SRCDIR)/doc/latex $(DEB_SRCDIR)/doc/man - rm -rf $(DEB_SRCDIR)/eet_docs.tar.gz* - ./autogen.sh --prefix=/usr $(DEB_CONFIGURE_EXTRA_FLAGS) + [ ! -f Makefile ] || make distclean diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in new file mode 100644 index 0000000..f9d22c8 --- /dev/null +++ b/doc/Doxyfile.in @@ -0,0 +1,1694 @@ +# Doxyfile 1.7.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = Eet + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# Using the PROJECT_BRIEF tag one can provide an optional one line description for a project that appears at the top of each page and should give viewer a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = . + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even if there is only one candidate or it is obvious which candidate to choose by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = NO + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @builddir@/eet.dox \ + @srcdir@/examples.dox \ + @top_srcdir@/src/lib + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.c \ + *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = @top_builddir@/src/lib/eet_amalgamation.c + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = @top_srcdir@/src/examples + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = @top_srcdir@/doc/img + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 2 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = eet_ \ + _eet_ \ + Eet_ \ + _Eet_ \ + EET_ \ + _EET_ + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = @srcdir@/head.html + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = @srcdir@/foot.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = @srcdir@/e.css + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = YES + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = YES + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.enlightenment.Eet + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.enlightenment.Eet + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Enlightenment + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = YES + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.enlightenment.Eet + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.enlightenment.Eet + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = YES + +# This tag can be used to set the number of enum values (range [0,1..20]) +# that doxygen will group on one line in the generated HTML documentation. +# Note that a value of 0 will completely suppress the enum values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 1 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = NO + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = EINA_MAGIC_DEBUG \ + __UNUSED__= \ + EINA_ARG_NONNULL()= \ + EINA_MALLOC= \ + EINA_WARN_UNUSED_RESULT= \ + EAPI= \ + EINA_PURE= \ + EINA_CONST= + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called Helvetica to the output +# directory and reference it in all dot files that doxygen generates. +# When you want a differently looking font you can specify the font name +# using DOT_FONTNAME. You need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = NO + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = NO + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = NO + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, svg, gif or svg. +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/doc/Makefile.am b/doc/Makefile.am index 5744849..f49a79b 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,46 +1,41 @@ -if BUILD_DOCS +MAINTAINERCLEANFILES = Makefile.in eet.dox -# install documentation -docdir = $(datadir)/$(PACKAGE)/doc +.PHONY: doc -all-local: doc-build.stamp +PACKAGE_DOCNAME = $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-doc -# rule to remove all old created files -doc-prepare.stamp: - @if test -d html ; then \ - rm -rf html/ latex/ man/ xml/; \ - fi +if EFL_BUILD_DOC -# rule to build documentation and copy necessary files -doc-build.stamp: doc-prepare.stamp - @doxygen - @cp img/*.png html/ +doc-clean: + rm -rf html/ latex/ xml/ $(PACKAGE_DOCNAME).tar* -# rules to clean -clean-local: - @rm -rf html/ latex/ man/ xml/ +doc: doc-clean + $(efl_doxygen) + cp $(srcdir)/img/* html/ + rm -rf $(PACKAGE_DOCNAME).tar* + mkdir -p $(PACKAGE_DOCNAME)/doc + cp -R html/ latex/ $(PACKAGE_DOCNAME)/doc + tar cf $(PACKAGE_DOCNAME).tar $(PACKAGE_DOCNAME)/ + bzip2 -9 $(PACKAGE_DOCNAME).tar + rm -rf $(PACKAGE_DOCNAME)/ + mv $(PACKAGE_DOCNAME).tar.bz2 $(top_builddir) + @echo "Documentation Package: $(PACKAGE_DOCNAME).tar.bz2" + @echo "Documentation HTML: doc/html" -# rule to install the documentation in $(docdir) -install-data-local: - @if ! test -d "$(DESTDIR)$(datadir)/$(PACKAGE)"; then \ - $(mkinstalldirs) "$(DESTDIR)$(datadir)/$(PACKAGE)"; \ - fi - @if ! test -d "$(DESTDIR)$(docdir)"; then \ - $(mkinstalldirs) "$(DESTDIR)$(docdir)"; \ - fi - @cp -pr html/ man/ latex/ xml/ "$(DESTDIR)$(docdir)" +clean-local: doc-clean -# rule to uninstall the documentation -uninstall-local: - rm -rf $(DESTDIR)$(docdir) +else - -MAINTAINERCLEANFILES = Makefile.in eet.c - -DISTCLEANFILES = Makefile.in eet.c +doc: + @echo "Documentation not built. Run ./configure --help" endif -EXTRA_DIST = Doxyfile eet.css foot.html head.html img/ - +EXTRA_DIST = $(builddir)/Doxyfile \ + $(srcdir)/e.css \ + $(srcdir)/foot.html \ + $(srcdir)/head.html \ + $(wildcard $(srcdir)/img/*.*) \ + $(srcdir)/eet.dox.in \ + $(srcdir)/examples.dox diff --git a/doc/e.css b/doc/e.css index 604ee7f..07ebd1e 100644 --- a/doc/e.css +++ b/doc/e.css @@ -1,161 +1,436 @@ +/* + Author: + Andres Blanc + DaveMDS Andreoli + + Supported Browsers: + ie7, opera9, konqueror4 and firefox3 + + Please use a different file for ie6, ie5, etc. hacks. +*/ + + +/* Necessary to place the footer at the bottom of the page */ +html, body { + height: 100%; + margin: 0px; + padding: 0px; +} + +#container { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -53px; +} + +#footer, #push { + height: 53px; +} + + +* html #container { + height: 100%; +} + +/* Prevent floating elements overflowing containers */ +.clear { + clear: both; + width: 0px; + height: 0px; +} + +/* Flexible & centered layout from 750 to 960 pixels */ +.layout { + max-width: 960px; + min-width: 760px; + margin-left: auto; + margin-right: auto; +} + body { - background: url("b.png"); - background-repeat: repeat-x; - background-position: top left; - background-color: #f4f4f4; - text-align: center; - font-family: sans-serif; - padding: 0; - margin: 0; -} - -div.main { - margin: 1em auto; - vertical-align: top; - font-family: "Bitstream Vera", "Vera", "Trebuchet MS", Trebuchet, Tahoma, sans-serif; - color: #444444; - font-size: 0.8em; - text-align: justify; - width: 80%; -} - -td.t { background-image:url("t.gif"); } -td.t[class] { background-image:url("t.png"); } -td.tl { background-image:url("tl.gif"); } -td.tl[class] { background-image:url("tl.png"); } - -td.nav, td.lnav, td.rnav { - align: middle; - text-align: center; - vertical-align: middle; - width: 100px; - height: 25px; - font-family: "Bitstream Vera", "Vera", "Trebuchet MS", Trebuchet, Tahoma, sans-serif; - color: #000000; - font-size: 9px; - font-weight: bold; - white-space: no-wrap; -} - -td.lnav[class] { background-image:url("n.png"); } -td.lnav[class] { background-image:url("n.png"); } -td.rnav { background-image:url("n.gif"); } -td.rnav[class] { background-image:url("n.png"); } - -hr { - width: 200px; - height: 1px; - background: #dddddd; - border: 0; -} - -p { color: #444444 ;} -p.tiny, small { - color: #888888; - font-size: 0.5em; -} - -h1 { - text-align: center; - font-size: 1.3em; -} - -h2 { font-size: 1.1em; } -h3 { font-size: 0.9em; } - -span.keyword { color: #008000; } -span.keywordtype { color: #604020; } -span.keywordflow { color: #e08000; } -span.comment { color: #800000; } -span.preprocessor { color: #806020; } -span.stringliteral { color: #002080; } -span.charliteral { color: #008080; } - -a:link { - color: #445566; - text-decoration: underline; -} - -a:visited { - color: #667788; - text-decoration: underline; -} - -a:active { - color: #88cccc; - text-decoration: none; -} - -a:hover { - color: #112266; - text-decoration: underline; -} - -a.nav { - text-decoration: none; - display: block; -} - -a.nav:link, a.nav:visited { color: #888888; } -a.nav:active { color: #000000; } -a.nav:hover { color: #444444; } -a.code:link, a.code:visited { text-decoration: none; } - -div.fragment { - font-size: 1em; - border: 1px dotted #cccccc; - background-color: #ffffff; - text-align: left; - vertical-align: middle; - padding: 2px; - margin-left: 25px; - margin-right: 25px; - overflow: auto; -} - -td.indexkey { - font-weight: bold; - padding-left: 10px; - padding-right: 0; - padding-top: 2px; - padding-bottom: 0px; - margin: 0; - margin-top: 2px; - margin-bottom: 2px; - border: 1px dotted #cccccc; - border-right: 0px dotted #cccccc; -} - -td.indexvalue { - font-style: italic; - padding-right: 10px; - padding-left: 0; - padding-top: 2px; - padding-bottom: 2px; - margin: 0; - margin-top: 2px; - margin-bottom: 2px; - border: 1px dotted #cccccc; - border-left: 0px dotted #cccccc; -} - -.mdescRight { font-style: italic; } -.memitem { - padding-left: 2px; - padding-right: 2px; - border: 1px dotted #cccccc; - background-color: #ffffff; -} -.memname { - white-space: nowrap; - font-weight: bold; -} -.paramname { font-weight: normal; } - -div.ah { - border: thin solid #888888; - font-weight: bold; - margin-bottom: 3px; - margin-top: 3px; + /*font-family: Lucida Grande, Helvetica, sans-serif;*/ + font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif +} + +/* Prevent design overflowing the viewport in small resolutions */ +#container { + padding-right: 17px; + padding-left: 17px; + background-image: url(head_bg.png); + background-repeat: repeat-x; +} + +#header { + width: 100%; + height: 102px; +} + +#header h1 { + width: 63px; + height: 63px; + background-image: url(e.png); + background-repeat: no-repeat; + position: absolute; + margin: 0px; +} + +#header h1 span { + display: none; +} + +#header h2 { + display: none; +} + +/* .menu-container is used to set properties common to .menu and .submenu */ +#header .menu-container { +} + +#header .menu-container ul { + list-style-type: none; + list-style-position: inside; + margin: 0; +} + +#header .menu-container li { + display: block; + float: right; +} + +#header .menu { + height: 63px; + display: block; + background-image: url(menu_bg.png); + background-repeat: repeat-x; +} + +#header .menu ul { + height: 100%; + display: block; + background-image: url(menu_bg_last.png); + background-repeat: no-repeat; + background-position: top right; + padding-right: 17px; +} + +#header .menu li { + height: 100%; + text-align: center; + background-image: url(menu_bg_unsel.png); + background-repeat: no-repeat; +} + +#header .menu a { + height: 100%; + display: block; + color: #cdcdcd; + text-decoration: none; + font-size: 10pt; + line-height: 59px; + text-align: center; + padding: 0px 15px 0px 15px; +} + +#header .menu li:hover { + background-image: url(menu_bg_hover.png); + background-repeat: no-repeat; +} + +#header .menu li:hover a { + color: #FFFFFF; +} + +#header .menu li.current { + background-image: url(menu_bg_current.png); + background-repeat: no-repeat; +} + +#header .menu li.current a { + color: #646464; +} + + +/* Hide all the submenus but the current */ +#header .submenu ul { + display: none; +} + +#header .submenu .current { + display: block; +} + +#header .submenu { + font: bold 10px verdana,'Bitstream Vera Sans',helvetica,arial,sans-serif; + margin-top: 10px; +} + +#header .submenu a { + color: #888888; + text-decoration: none; + font-size: 0.9em; + line-height: 15px; + padding:0px 5px 0px 5px; +} + +#header .submenu a:hover { + color: #444444; +} + +#header .submenu li { + border-left: 1px solid #DDDDDD; +} + +#header .submenu li:last-child { + border-left: 0; +} + +#header .doxytitle { + position: absolute; + font-size: 1.8em; + font-weight: bold; + color: #444444; + line-height: 35px; +} + +#header small { + font-size: 0.4em; +} + +#footer { + background-image: url(foot_bg.png); + width: 100%; +} + +#footer table { + width: 100%; + text-align: center; + white-space: nowrap; + padding: 5px 30px 5px 30px; + font-size: 0.8em; + font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif; + color: #888888; +} + +#footer td.copyright { + width: 100%; +} + +/* + Author: + Andres Blanc + DaveMDS Andreoli + + Supported Browsers: + ie7, opera9, konqueror4 and firefox3 + + Please use a different file for ie6, ie5, etc. hacks. +*/ + + +/* Necessary to place the footer at the bottom of the page */ +html, body { + height: 100%; + margin: 0px; + padding: 0px; +} + +#container { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -53px; +} + +#footer, #push { + height: 53px; +} + + +* html #container { + height: 100%; +} + +/* Prevent floating elements overflowing containers */ +.clear { + clear: both; + width: 0px; + height: 0px; +} + +/* Flexible & centered layout from 750 to 960 pixels */ +.layout { + max-width: 960px; + min-width: 760px; + margin-left: auto; + margin-right: auto; +} + +body { + /*font-family: Lucida Grande, Helvetica, sans-serif;*/ + font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif +} + +/* Prevent design overflowing the viewport in small resolutions */ +#container { + padding-right: 17px; + padding-left: 17px; + background-image: url(head_bg.png); + background-repeat: repeat-x; +} + +#header { + width: 100%; + height: 102px; +} + +#header h1 { + width: 63px; + height: 63px; + background-image: url(e.png); + background-repeat: no-repeat; + position: absolute; + margin: 0px; +} + +#header h1 span { + display: none; +} + +#header h2 { + display: none; +} + +/* .menu-container is used to set properties common to .menu and .submenu */ +#header .menu-container { +} + +#header .menu-container ul { + list-style-type: none; + list-style-position: inside; + margin: 0; +} + +#header .menu-container li { + display: block; + float: right; +} + +#header .menu { + height: 63px; + display: block; + background-image: url(menu_bg.png); + background-repeat: repeat-x; +} + +#header .menu ul { + height: 100%; + display: block; + background-image: url(menu_bg_last.png); + background-repeat: no-repeat; + background-position: top right; + padding-right: 17px; +} + +#header .menu li { + height: 100%; + text-align: center; + background-image: url(menu_bg_unsel.png); + background-repeat: no-repeat; +} + +#header .menu a { + height: 100%; + display: block; + color: #cdcdcd; + text-decoration: none; + font-size: 10pt; + line-height: 59px; + text-align: center; + padding: 0px 15px 0px 15px; +} + +#header .menu li:hover { + background-image: url(menu_bg_hover.png); + background-repeat: no-repeat; +} + +#header .menu li:hover a { + color: #FFFFFF; +} + +#header .menu li.current { + background-image: url(menu_bg_current.png); + background-repeat: no-repeat; +} + +#header .menu li.current a { + color: #646464; +} + + +/* Hide all the submenus but the current */ +#header .submenu ul { + display: none; +} + +#header .submenu .current { + display: block; +} + +#header .submenu { + font: bold 10px verdana,'Bitstream Vera Sans',helvetica,arial,sans-serif; + margin-top: 10px; +} + +#header .submenu a { + color: #888888; + text-decoration: none; + font-size: 0.9em; + line-height: 15px; + padding:0px 5px 0px 5px; +} + +#header .submenu a:hover { + color: #444444; +} + +#header .submenu li { + border-left: 1px solid #DDDDDD; +} + +#header .submenu li:last-child { + border-left: 0; +} + +#header .doxytitle { + position: absolute; + font-size: 1.8em; + font-weight: bold; + color: #444444; + line-height: 35px; +} + +#header small { + font-size: 0.4em; +} + +#footer { + background-image: url(foot_bg.png); + width: 100%; +} + +#footer table { + width: 100%; + text-align: center; + white-space: nowrap; + padding: 5px 30px 5px 30px; + font-size: 0.8em; + font-family: "Bitstream Vera","Vera","Trebuchet MS",Trebuchet,Tahoma,sans-serif; + color: #888888; +} + +#footer td.copyright { + width: 100%; } diff --git a/doc/eet.dox.in b/doc/eet.dox.in new file mode 100644 index 0000000..e69de29 diff --git a/doc/examples.dox b/doc/examples.dox new file mode 100644 index 0000000..b842584 --- /dev/null +++ b/doc/examples.dox @@ -0,0 +1,184 @@ +/** + * @page Examples Examples + * + * Here is a page with examples. + * + * @ref Example_Eet_Data_Simple + * + * @ref Example_Eet_Data_Nested + * + * @ref Example_Eet_Data_File_Descriptor_01 + * + * @ref Example_Eet_Data_File_Descriptor_02 + * + * @ref Example_Eet_Data_Cipher_Decipher + * + * List of examples + */ + +/** + * @page Example_Eet_Basic Very basic Eet example + * + * @includelineno eet-basic.c + * @example eet-basic.c + */ + +/** + * @page Example_Eet_File Example of the various ways to interface with an Eet File + * + * @includelineno eet-file.c + * @example eet-file.c + */ + +/** + * @page Example_Eet_Data_Simple Simple data example + * + * @includelineno eet-data-simple.c + * @example eet-data-simple.c + */ + +/** + * @page Example_Eet_Data_Nested Nested data example + * + * @includelineno eet-data-nested.c + * @example eet-data-nested.c + */ + +/** + * @page Example_Eet_Data_File_Descriptor_01 File descriptor data example + * + * @includelineno eet-data-file_descriptor_01.c + * @example eet-data-file_descriptor_01.c + */ + +/** + * @page Example_Eet_Data_File_Descriptor_02 File descriptor data example, with Eet unions and variants + * + * This is an example much like the one shown in @ref + * eet_data_file_descriptor. The difference is that here we're + * attaining ourselves to two new data types to store in an Eet file + * -- @b unions and @b variants. We don't try to come with data + * mapping to real world use cases, here. Instead, we're defining + * 3 different simple structures to be used throughout the example: + * @dontinclude eet-data-file_descriptor_02.c + * @skip typedef struct _Example_Struct1 + * @until typedef struct _Example_Struct3 + * @skip struct _Example_Struct1 + * @until int body + * @until }; + * + * To identify, for both union and variant data cases, the type of + * each chunk of data, we're defining types to point to each of those + * structs: + * @dontinclude eet-data-file_descriptor_02.c + * @skip typedef enum _Example_Data_Type + * @until ; + * @skip enum _Example_Data_Type + * @until }; + * + * We have also a mapping from those types to name strings, to be used + * in the Eet unions and variants @c type_get() and @c type_set() type + * identifying callbacks: + * @skip struct + * @until }; + * + * In this example, we have no fancy hash to store our data into + * profiles/accounts, but just two lists for union and variant data + * nodes: + * @dontinclude eet-data-file_descriptor_02.c + * @skip typedef struct _Example_Lists + * @until typedef struct _Example_Lists + * @skip struct _Example_Lists + * @until }; + * + * Let's begin with our unions, then, which look like: + * @dontinclude eet-data-file_descriptor_02.c + * @skip typedef struct _Example_Union + * @until typedef struct _Example_Union + * @skip struct _Example_Union + * @until }; + * + * The first interesting part of the code is where we define our data + * descriptors for the main lists, the unions and all of structures + * upon which those two depend. + * @dontinclude eet-data-file_descriptor_02.c + * @skip declaring types + * @until _union_descriptor); + * The code for descriptors on @c Example_Struct1, @c Example_Struct2 + * and @c Example_Struct3 is straightforward, a matter already covered + * on @ref eet_data_file_descriptor. What is new, here, are the two + * type matching functions for our unions. There, we must set the @c + * data pointer to its matching type, on @c _union_type_set and return + * the correct matching type, on @c _union_type_get: + * @dontinclude eet-data-file_descriptor_02.c + * @skip union type_get() + * @until _union_type_set + * @until _union_type_set + * + * With the #EET_DATA_DESCRIPTOR_ADD_MAPPING calls, which follow, we + * make the the link between our type names and their respective + * structs. The code handling actual data is pretty much the same as in + * @ref eet_data_file_descriptor -- one uses command line arguments to + * enter new data chunks (or just to visualize the contents of an Eet + * file), signalling if they are unions or variants. One must also + * pass the type of the data chuck to enter, with integers 1, 2 or + * 3. Then, come the fields for each type: + * @dontinclude eet-data-file_descriptor_02.c + * @skip Usage + * @until argv + * + * Variants are very similar to unions, except that data chunks need + * @b not contain previously allocated space for each of the possible + * types of data going in them: + * @dontinclude eet-data-file_descriptor_02.c + * @skip typedef struct _Example_Variant + * @until typedef struct _Example_Variant + * @skip struct _Example_Variant_Type + * @until }; + * @until }; + * + * The code declaring the data descriptors and handling the data is + * very similar to the unions part, and is left for the reader to + * check for him/herself. The complete code of the example follows. + * + * @includelineno eet-data-file_descriptor_02.c + * @example eet-data-file_descriptor_02.c + */ + +/** + * @page Example_Eet_Data_Cipher_Decipher Eet data cipher/decipher example + * + * In this example, we exemplify the usage of eet_write_cipher() and + * eet_read_cipher(). For it to work, make sure to have your + * Eet installation with a ciphering backend enabled. + * + * We start by defining the information to record in an Eet file (@c + * buffer), the key to cipher that (@c key) and a dummy wrong key to + * try to access that information, later (@c key_bad). + * @dontinclude eet-data-cipher_decipher.c + * @skip buffer = + * @until bad = + * + * After opening our file, we simply use the first cited function to + * write our string ciphered: + * @dontinclude eet-data-cipher_decipher.c + * @skip eet_open + * @until eet_close + * + * Then, after closing it on purpose, we open it again, to retrieve + * the encrypted information back, in a readable format: + * @skip eet_open + * @until eet_close + * @until eet_close + * + * Note that we do it twice, being the last time with the wrong + * key. In this last case, if the information is read back and matches + * the original @c buffer, something wrong is going on (we made it to + * fail on purpose). The former access is OK, and must work. + * + * What we do in sequence is just to delete the file. The complete + * code of the example follows. + * + * @includelineno eet-data-cipher_decipher.c + * @example eet-data-cipher_decipher.c + */ diff --git a/doc/foot.html b/doc/foot.html index 0d3303d..3a96978 100644 --- a/doc/foot.html +++ b/doc/foot.html @@ -1,6 +1,20 @@ + +
+ + + + + + + -
-

Copyright © Enlightenment.org

-

$projectname Documentation Generated: $datetime

- + + + diff --git a/doc/head.html b/doc/head.html index c2ec935..519631b 100644 --- a/doc/head.html +++ b/doc/head.html @@ -1,44 +1,65 @@ - - - - $title - - + + $title + + + + + + + + + + + - - - - - - -
- - - - - -
Download
-
- - - - - - - - -
-
-
- - - - - -
Support
-
- -
+ +
+ + + +
+
diff --git a/doc/img/e.png b/doc/img/e.png new file mode 100755 index 0000000000000000000000000000000000000000..b3884a5cbca7bce5747eb3b8a92145d60511a718 GIT binary patch literal 3825 zcmW-k2|UyPAIGQMS98Ry6)m}iA@`NJZE_o#Ovc73e^-^QHU$G0h_3|cuDljd5QbT#Je?6pNPP^G($^aTorE>q=yral%n2Rktlk|u< zB6SbBG`&ZF=tG%tj9|RLw-;=+A0K(VYgY{_m@_Mu;#9$;A9&jo($nUG3m{pPG9sKJ z)-SrEJ!oZpgRkTbv#N2w?Avv1g`*hj3@X!Cn+Jh2Ml;^V7@mz6b|Fo-YFT&Oc=qw1 z@}>V_jJMQ>kyo}tc5CX?e65}5iLW`a*?=JPI$Jx)*JdpOpdFk$7LNZlSowU@cr#Mjx)>#Vh2qRYMG@4%U~V=*(;bxq6%o;REM)$>G`C7nd~m&p*#P>~ zXHur`Yquq~Y&12(1U{S4izUj!VqeX6#jVc9i4wfL*s)~-o}QjXMEK_BCOa2bR1e|w zfOiwc9TpT4;xRu`3f2tu^&xUXTv-ZkyvdBZz~6YF9A*}l+0tzM1w6ihdTKaGCcM-b zM}+kR##h<)t_vDPGSvAu;zhryW3SGaF8dM)M|gO64tMi+Iy@ydmbFeUae-c2{QNoG z(9m#bJ|Lb-MPIsvICAtT6Qr%J&FlJgLwoz<%m(`4rx$N)fyA(+zm0CXPABZ`Y;G;L z{_bdyy$#F#KH(XXsO3Jb1Q#zc1fq{*U zjYV~JP>U?NSCL2Ad=K{iTFJ6FGWAV|A0&YtJIM(N3JQvei!+~p$aC|>Dl6&yL|#Xg zIX+2Weg&eas2K77JvQjh9i*O~D5!_YojcEE+(AXktE#$w{w%LP_%H5M=b04kBWh}D zxc2O9VLyNW)gECtF*P+|5T~J=o2apg$$#_(d-_h^TCnHtq71c!2zRWxWDpjn!_UuO zcWv<0kxLtcNl8iN)zxTQTLC2}o9m(byTL;$JWs}{A3oS^ZEvS;Z{E>Cp-_rSN|AlCExY6x%V{lP3aGQ&Z}<7hzfQ zF07zj10`OsC@iK}tTCCaB&2|+E-(9l0(Hy>@X!C-*+HtR-ujI2c$AdYyXh^~)F4Il zzzMlLC8a)YPnWbhjIFPa%gD$GmE?PCduwZ^?eCPKudkxBi;LOH8N8LwW`;LSS$4%) zx?ENsdRA0Kgd_bexl4mJQOGB;;>g}!^1**?gy$7$wPR|Ei zVs8!%jpMNr88)kWN^?ogde$9cWo2b)X&FJ2;y!k)F9OgLp&JTI(cO{q^YfcwF#H{j z%mHD&8k`>k(lj9Q-C;Og+VS&=mg%exwn**okO~FI#6R7i^cR~amJZy`{L_nl_Uzd# zP+riFoNM<}Q<iF240XUkipnh)?rRKXHCsH%<~~eP9Nw zkqau%sz*Z!{@*$FcNP?o@?cZr%EaUjMedC|I-tV!fV+9RVQ_4jZKfCbIfH;Kg45E_jJnnwJDq^pApCdwVgPKmHB z!=6@FPNzCr)C6drgvA1wG8MJ9x;!~AS&DhwVSc;3B#qv%<6L7Hx)0{h+mg+0 z0jqK$SZNPm{q3QtspPPKfBq{eiS~+YJS!pb6?`OSoRqamr_%>N_q^qN00y+O`IQf2 z+ONq@jb3~&ch@XXS3^S)t+$ts^fgp^l*D2hS>*bVDk_42(C2Bz#jeZyq=~0Iw_8tY z=KJ_03RcSYhZI2ZA^5$2n^Z zhKHkI8AsB4C}Cb-U2XZaezlWJK@9Yhu?X!asz+tBKS$Zr%IdX3`!1>nqM47)$jG={ z6Hw*j?B(e@8paOM)YQD_>MGBrf)C%jMf%)G{A_Ab!GaWc-rAa)nHj@)ozmsgEFfWL zXIE5Pd(7NL^`S8bMGS3ZguyK+PiESq78xme#+H`U#qGE0lGfJNvkkwHO>4CJD>xwo z1A{jM11ylm>2^1Vo*e(Pl1LDQ5Ws)HygDLK6i)xZ|&>dfsOPKeXm+M(}+hAe4X z6^(1_>#6teN95%pc2{4Es^8g=`ug?jBeWA}$-@!V(E(v)V{=!8L18fV@bGXsTtjrf znx^KxYlUG#U=E@&U;>bLx5xnj0W$+?(|PNsIb8382bo;|XlLL`xUQxqTtr0V=kjuF zbF&(t;zeg?&f;NqvRMLSa&mHZZZ58_PO-bU7l}ggM@B{}!jl?)gFFKHeR&Zq0D+2% zretIY!nj${CML!8^?U#T%DQSrV~56cXy{^gjJZ5-NJt2yBl4*FtzUx9&dx=n^A{Z* z<3>hoGP1Hd>2zVBB+57`HanY674K}2^S*xF8jnx@@#E^^RNIN1oSaWB#cMgJ*Otw*rB&I6XkW|M$G6uvyt`6=4Q|K`kZ_71o=n5$YD92 zJ{1C@Q+zl8Tt!rSyB;@d6scf;|L*S2Lai5x)ZLRPtfZ|?1=~Oy8x#I6Pp+)3br$G^ z42_NbX`h$s5(7DsmzRH{J7@@G0_>a>lRU=kBQ^b#^fF9~Kp@mz9e@J|CF~Z; z=i}oO1g5^dRdnUai@D1~BN_7E-_c)hH&#LIcW)}f^hZ^u!v4CB{}Fsm_VV)Tm@5qD zjdcf6#)5f&1{ecDqyO64P9`KI#K*@&x)g(!n&@@JQ3+sRI=q{XKyeVzcDKRmK@VQGJz^%tG zO*DH_jWQ#&1@Sat zu45x^o;XwQrjLI%y5Cr6|6eo|$`MN}mI6S}%?;gTi+K0Wd__BDY6`#c=MU}03j`ox z^qWHiar!iqj*br68Cc1Nu2gRuM_H0oc5HR5WMzw#YBJ+Wsm%9p=9#t=@;89dymqau zKP+D>F!{yAmoIV_{<5;N^>;SCQP(Ui607kFI%@i(8yU7p?}*InZkocy4qt5dWs-8? zfgi_Qz*j9%K=LhN|IXK+Sz20ZXd>1-)p-pgacyfrYz@IHW!3PA`y{;&)10m6HA8F8rcC*>aa z0M$%EMiP4b_amphC?0$U!%0@}Jp^G9{(DD&(lW@vC(&Hxl%&vpVLd?;K!}OKo`WD7 zNKR5r(_{Y7$NeLb)~`o*tFMfv@iC~Mo{PdoLogU}Wn~J2=`cfx_Gm)Z>0wf$wsaxr z{zS}}@{?n1n#}4_1%bwiF@Zelyy^DYxA!&fap{9U7(d+zkN$aBzWume*IM_V`?1LN z;`^T>#ITib2|J84OWjP$8M7)KZxNgz&CLX#Plo0{wuX~05Q=>t@2`&_VMdj#MM^jt zL=6c}H1#>~=~U<^iZ2`Dh+f_Qxi;{9xZSDm{`>?h+xKp-6PJ>o20|C~IL(2&;(1Dw z4rsButpEHz5{9Qi-w~!FqN7iow}yx>ZZCGI5sHy=`n*rtukqnI;03V?KC?m6l$~A+ zUmcRf0#I+?t#tU1LEDomuiN{bDRq;2LkXFnobB_i;S-@uWz8yMDv0-$*QE_TRAt&7 ze6`r-dEt&dU6=MWQu_LKC;Oe}&8g}8nq089=$rfNl`4c)tC6%1NjsjwJD&WR%527M z{FfDt%kug)W#U8Wgzs)==WXXokSW$V`QS3c_g? zr|Ea2qDhRR$EqJ`0bQWhyhd9nBXauCjekwVnK8Y24(5u(!8&g5!u!jyabvwVJpb-;FFq+g9;s{^GrSkEY+8T4 zwbx8cU44R%nmU`mXi|@rot=FZEck zmcqUsi6=R);HIt;oAwwq*zg?fG6kM(xg||0ZWdfoJopSZPM9@z`_E~p1qn}BSQwc+ ztP46t97FFiN$vZ-YfT0<^t_gkka(k=gJM_fxS)Y!luV8zyqoKKFr%bO6Gr*TnGkXK zZu99&+~6|?_~9WcFCs+C$S9prY&VfgMCt{Ddu@*5LQ$=@rvlKO^G2T~6oP#ERLSe* zRD?E~YM1k(MA772s;YL>Uuz}~LxdbuI2Gg-=XOqxA;K3UE#Pln1N}s5Qh3^|WL1d? zS9FPv%_xM*5mu2`pTN<^u)A>1RT0FZ?OopBLKJ&75}`p{7B;-xZ-WY$f{@4D&Z#9{ z4f_-iN<8Iu{Yvyyxc6*IF(o%fL+RBAD5Y`Pi#6r%sHTODAas}Z^6dDER%WHY+H&prC*i;#q3>P*&%4wcjvZrn4guRW{S^eXS1(x3{(V>r@&0 zI4-w&Cd-+Zqf-Z)lD!kd)Ag4*+?y;q$rf^tBK9njE%nSo8@=!V1!#xmpR?up${Va9 zStj}!6>b-u+xYv50=X|79XE6q`%@*+nk--kpmcNo1eM!}x_StXT=b%2|H07fK}XlVY{}+MZzTDq|y3QR7bE`?L@HQ?~2r?>Yp+x?Xzxy*VSzP-dF{ z>hPAD*FJ?qk4mb`oRr;gx6R{>4wO(7l~C#9Y4?*s@9X0&n+|4l#IN>q1n4v-U2ue7 zpm+!f2tFcgPDFaTf@Q%s_$gm~mDt${s9F_W8BxSC;}I)k>~lCo-`@b&NQMKD^3lye`$2nk*6T ztX$teV>!jr_qp+Ue_6g$%nx0T!F;4SOr7NmN-*IzPsCv ztzsel+99fd`g6!eJ|#f4uLNOrveHOM;b5jBa-#2tBn+eEP3MCbB(lhpfYBALs0|~J z4SSaNDFg8v2Q3fJB@FHec_Hj7r5s_Mot^ndN2`eVBTNq}?iX@u;Ikh+F?k_o^2y(l z>a0$?LSF?P^@jNjIjT!srsYItGsFbi7%UR)nKU_fsnBGP?`DqryCauU^<-@mH7wsi zb_2#ip&6@EgJ$P$ALWhuh0Vw<M19zU-wyWp{Z^h)MsaVn@7tPck>IL|Z3mpXie4i=l=GeR8@b~3xsP%5|O5E8Tu zwSlf2@4C^46C1b-c`!YHz8M=8KDLR7gfw?PB)6_Ub~0DD;|gYol-}~`lKTq7d&gc?a7#V4tWWCwlExz!AMwM9 zEi-p_chfmK|GKzCQDCAlfZ=#591W%hDl|Zv+dqJwtF8dH zx_UqVw#qUj(^QYdpN7bOxviODE>1Vg`?wk2;qzx%Q9&U-Q$A7}2@EMq(45lcn0$h9 zsqQF-Ydg$#ki|sh<>ebU`lBBi86sTpF80RrWrAmEgH5Z!r0;{cA>Eyk^y|%`MAn!v zeHRTmKgQ?Jk?|>Ub|;HQiEGS-N4r;6{EoLr(qA)n@@aW$%IdaPI@Mr5=aMmE zWx&{R1BR&*vY3aY6Rg_vV!M$n*mNsLa~XGgbJMj2bfFK>w3)eiRR~p?Q7bQKKiJ6c zJoRs`F>!E46y)Xe7Rr%mA|u2lQY^I~t^EA_=;Y+WajG)CIz|A7@FdC3kOnIdkUwWK zBv3s(JOmLi7k!aLV`YzGkt7LabV;qF%u9wuPcJT7<&gJPQy&91FX>S8XkaZ|G&Cj@ zrp)q`;u5;5FnFINd~stR9np*T==GM z(eh#4l^c`06*9qr-zJcB;nI+cVu>SHA&&9BTc#{2DOrhlCere`d##!xvai&tuGwVr zi;^$yXC%qNJ>=7_g#~X>W8-B#?m}Vsl|@dT1zn7{XH%?6`@pX7pl9OYSvQ7rB;qME zxq}k-5-;Kzp4uDHV;uTXMm(=Qv3Xt?t;h!I3Yk3ixT=8~>!)L3XgJiVpO8lt-$oGK z9UaLjGK44ZcuHIjAN%DM@vq1*X}(ZXNeMxVB6J=J9Xmsxq`HI+b@agn*ad16%NOhV6ogqKbi<>{lcnK ziJpL3whv&cRIKcioS~6)zW3jZ7svDSy>qjF*%0q^O2w zKR=7J23oi{#LW0RAU3IP3rg$?FQ zM-oU`vIfoKii^I4rogcKBVM8XdC#>4Re03=boHB9UWo%}_yPb2{mu(JDYa;D&P8o0JIfaO}J*U|ljmC#Pa&E3ob{3( zfR27uJd3aInK#9(e~m{%;#TMP_^<>O@BB!8f14luDhx6Kz$I!YhE^hO`)B4`8jU@Z z=jn*utpMt$*w|-ee>|5XgQjEYWgY}Q&!0=Yb?H%I@CmF3jW%F||3}(OR!X=JfKRMf zUOw-#cFw?JgHDCB6)c(wj$wA-O1gu6);2c&bLtHv{s5hVp(X3WPg$EeI5Hw~fA#Cl zC{L>5dSCJtc%$Sp>%mk}8HEXioC!zM%S6?;x$aGDsO3xh?5(YhUxagX6f2k8YL`@o zqvTv)UEvH24kAEpx7+D{<5c*s!FZmJv$>LFo|cot&iigWT5F%^zU;XZVc3uROqk3a z>?Nk|V4Od0pe~jMafg{@2s8t6J(bgVn5XS|lXu4eW|esal+ZeqYXDP}lMH)bE}k*6 zLZ@o^LQYPOln)H^V=%S3)zar!l+t)?mqAO6oQQImt)@*tj|fUQ)GF1WgzihV%Hja% z*idrcJ*et*6f=y8fNrS${+|5=)320;)+_s!&kcC9%bP%fubi%R`xOa&`E_sxcHAvN zvCtyR^4-;ejyOfr+h3J4ZmlB3qQ04eA3kRJJ=}WB%d$`ZoT@bP?guoM5r3JSAMnK$ z+s*5Xi}XkE4PN9VI+i0B@tkx%`nL3%eewX)DWhiLXb(E4r>74{=dpE(eps>R4S0AV z@@}z-%L&|&U+6zAL_AJc>F3Q^1O#r8YR~lqG_cTe!ld&(Ra_+iGWm>4wXgi!CnP-l zkHRJFJwK&X_PTrPlJRBwt9Q$7dvkeGSmtJC>vL06Q)s59ri4_uGUN9h9UU^yUi)US z(FrQNtGl~CdCVQLVtp#5uRl-VFYyylcgvQ55F)dQ70{S323jM2RT>>wH|U$z&6(8A z;gOSj2J&i-XR4=%hT+B!CWv1M4mea* zXqPo&_wF#a=4S32%0Qh-@Bch6^`(3Mi&}vX*I!eaQ8n(rr7%@in#z~agLA=6!LVmQ z3emh7{?H+-)2rU@9`a0l3cp|s&X3OO$%rG$;=J!IR-(b1KEels?Z!?mh%K_K?w`_; zXe7ceZNvRVwW%~vql(eHE2I`-qlA<{pnhZ9^CBtQ&GD?DNKVdiU_fZ z#s_fSvTC+b+(9}{!a;FEWcQHu73K>?G;yROm-B>p9xLQAWpRnswKdbiuS=Fx>vRM3 zWAY4R2iPXaA67ihI}r8HEg16aV=2xd?7S6qU0rnO>)6;>4YBGDKd1^Jg5ttBEf(=3 zn$*PO`YGnJ-)beAu@b@9&9bh$k8u);iSi79McOhIzKqQ>F4L~?qFa9LcBrdnz9FHx zJnkg$MyBm0(=aRTam!XHbaar__6iH7<;EoUa0d8$|Nsz1HM(m z&&NvZz#Lbcs5u^;XEwuCLt5pJdMm2v+5r9CJUV)T^eS6S9V5{)C$&ub%+^rDt;&Ps(O%MF{k(`Qp!35%Lv zTDop3xV+(mD(q&;1!D0Am;+&aj2gP>u0x{e9-)~LWFebKU0~KUM67Bc!>a*n{EI8< zaZu5SY}T+ZzKF6hINbYRmf;Cv&OMNSxW(EO2Xo#c*_d#WNou6??Ug4dkkkg+h0AMD zamBx+p{cxG59iocI}XNy(Df^{(Q$E?`TQO}9-vWwjNy5|tw;}l1#kvw?$t9>0gAyB zlXIcCAJR01^E0xA1k!mlk&I6QV@9ENV-CDwO@|>%XFffmJe0R0p0-p&M>K(=3*tPU z>qA(K9zWy&?YWr3+h&m#w!z4ohf$Y4pCHHb+N_naMqp1=imk7X@e{eMS~I~C(vYv6?L?og z(KUSwE*0~_GebpZF;-s{j;<#vI%H5da>$;Jh=r1}-4Y35G?}SC3uh6RPpFX>6i>H7 zVIY)g{`!t+vnOgI9UY<9nT=NtjdH54EpFt-R)}FBgh_c{P=)y#C3LODPYZu}Ii#XllykDjZ77bgI~; z|1|wF_EvgSF$j8;Q~2)y6^{j)2Yl&-;iGsxiwl87m9?~VaOwcASE@G;bh!i6MtSn! zC4`0v_@FjjPE$+_-Uxss;)9Turi_$w`QXsd-5D4d%3q)_dCEA3xEF#1tI|lCuK43V zcY8$@65`^5>Z6lzeEQQV0Q&w!BJy0EAd}=fk=UY8i+J_)_VxL;0$h0p!!6_BniX=@T=>0dh9>U zS!#bkPC)+gt1)VI!)kFqSxzI+MINHut8rNPN;EzT1ObkJZNLXY2P4p!RlB^2em`l% z>b;Ay^3Nd9`Qrg>e7KlzcuNj++-m)b2>puS#>PfGeEi(VkPsV6e0==3oMifYS9fGd zmI7jUr<;TE0RRM1Vu+FnxLEv9;ApRZgMF4RBpv~>hXJ?Z{pDv&NJ_6%5|}!kfB2VxgE}mVPIgay!JeojKM#Zq&wt#J5$~O zzEL|_@F)2~e;Ra8Kot(kwactdmfPPRFE*R!_Sk+R%Si!DrqO3BQO61e6?NwE&q-%& zdO9nrcap7@TG=!@I=ZNnQ}qSd&O03scL#I8FKFdpg8xk6+E5Dbjnk;mZ|HdS>Xma) zP>>Ywk^71dUxIxgTf)~CWJN|`UHEPEMGF0}`j5lfN&@JtRaO-SjSt3n$c#)(*8M;^SSgHfU-$U|=7QN9 z&#lCKfbATbtVgpt84QTTFm&ypG$5e`eYKt3=I(bc)~oyC1TK%^HK20y1qILFM?VuW z(*T-1yHQI518<)*Wh-F5J}Ozlq1;a+3*q#nMd$U~%1?D&qS%3qbhGxEdRed0amlzP z)bIY_jRCMJE}r%~i-TT}4yf>7EGQQ+rD|O^ze?SjJc@?c0>0?lT*dmgd0D1p(Tyv< ze-K`p_ySL3O}k7>F{-QMdfEHkbg`PbJkTqfp$*(RFdZ_pL^IHYfwq$;hglVIZoj1LikByCu=*N$L*#f?e zHh#`Ba~wgW(jLg?9sy#`E4eWWENDboP6<1F=aa}TRHhZJx`7h2sffp ze_}r~Xms=edoCXPt(8u>t}{$Ppc!0fFq^3k-Ea90bfDXB{M%8y);}|vWt{C^%;9_d zYgwI6lshN53qWfR2ZRSjokh`F>XQ_bJfGE%lsQ{l+mohzB>-b7+`yI`hV41Q04Vkh?FB*X6D*QNN=Ng2%qA;L1PQ+Er$lj-I~8W;~B3&-JU8 z1^L9K{4a35_{v4^Q-u&8hB-QW)a*Q2q2-m8mG?sl%yOV8UL*@M^j6mj8*FZJKsG?5 zSqGh6DBSp!#mU|@=yv(o-8V3V3a|>@dK)zw%Vc*^+8m>nW^IJA{VT7P-$x6tpKDt; zZ}o%m#FK=WfCK&Kyxv0$dbZC96`X~zt^i(U(8%8L=eV`Htxfp9FeH>R(CpS=!?nKh zdD4oCKSqF~kyp_ZE5^m0&X|$~T8DzNqT-ZnbC$i+86F$uRn|KQAO@*U1Y~g>dPxzD+6ufB~iOnpk<#9x*iHL}R zP#6cJ%D73*&VD=t(hJ|WEk1kN#yubZ^Z@5VaiD)9wjg3i>#YkGQQIV9hgvrHYx)k3&*TnQ< z{hxyyUvJKU`|jPlo7-E<9DX7-qD`BH6k<_RK>R$^JW0vP1>WS3*FO|-DR^a?raVB) zQqKEW>2vlE0UJ%*!lU#;LKJ2$3j3)}VtAG6U(HbAIqC$Gk<$6ehBD{p=O(=A?=%dE z=T%`X()#Fqp-&a>!H`>izVZP8#%w0U%38Q(-CS5(ja0NfFjdRT*@D$yTtFFofPi9# zzJd98czOnH@9eC^6#L|;*G|N!n#@V$k5ARl*-zY4sxWV51g;tk%PdB&%b-ENrqBHexX{R@+-wB?HDe#g@HSc z9AOhzWRnxsPU~-59GbSkfBjj+?LB&YY#|)pdyZ!*$rpZ}_zeDOqbWHnaKKZ3w(X#PJeg6n?Fg5&;9RuI2INb>%lW7Lp@*eJ<3sRsLs+tjOsrt*ao^YrCCtZtpHEYwZJN z1SmRwI0Ftx;Rf(&wA8pGbu2v=stGLL#9Hc$ukb)tNFER5%eR<@KjF=ihc&YOdG)c| zvP^9-I29dP(Q{=QPEIE)7ngJOeTKv}+#XqEtHd76ie!XEG^bnkQ6Ky8fBxDmtLpHISieE}ZA&Q;R$T_ba1p?^#KX>%X?*WG z9uMd0CPP0Kejd*El8}v;!jhY#BLO}xMqM{Z!U}9k23L;z5r{mX zh4)V2vHNXd#z)cp=L1?xwk+pXhkW5Y+NyU`+t-CIV!WvU*~{;Kci8CYvr0*CFqj0y zl}o)nJSc-$r3WODPZtJU-NCkK;7(VTz>q7Bz_;L*)v zR5nF>8pg_)d{fX81w3^XOn1$WC0LJB2WLqTlHa_TMo7_|ygpNs>6Sula%5GEO0LP>_%ibB}qR0!NebD$Vt34D}7-cS%((i0oIk|TziAvk2N2KS9_T*XHHIQcC$}9Eo zKxjZU;0MZ;14;PSGO*eSxw*NO)#jm+>{1%F+f#_FLYrb1I4-Zi;t#z*5QIg@?a)U2 zVL`s>nQl@Lm;@HQ>F;4@GMlb$&@dQX9~BuV!xO$r-Z?TYB7Ygc_(=I748ON3W{X@} zl`rFCl~_ITOWBxAQ6AJax=4BjuXtn$W2W>ivhO^barUodX8(!|`dzJtEn+e_eC{Tm zWtNnbv}e>0-iJkfBK*V3-Y7vNmMo-~5R1B;X-{vIb%~7*X|g1iR&=k;it!hc9nl|? zlOt-5pX=+G-CM3T30J*i!X_y2*tY{I};&SsR9rE!uy3Y-1cG`Szl=R;*?c(VlFQ1*oiMu^vt~EpD|{i{!JS`1h7ysmpHCL5Cy%Kr z*j=UZU6c$Xnc(>my5%Lx3Q88&Kh9mFRmFOlAx-J%oK0;ekLDX1 zw9BqIVAh^297lf|k;;lCs03ZdSWJ{+&**u1-2x@=HRyKRfV*%6QbX&if?8s+`!*wK zFA2feBDAcolAO8+wbuH#(Rn7X;s=0)Rr#|lib#@5ib~7O%*@{dF$nWQn&qR-=u4O& z;21yNuY!U{F&iosXFitvQ>db@9`^y1jL6`-3Q43g)EuKGCsU15>c`)^f4HxVr1PE6 zth0S)P#KVZDm-rje4Y%{)-$_oSys|%Utiy&2x)q-wNV)YegP%nUj*m(<{;q+cnPJr zLVY^jzrCbygoEUjW7HU{VVxt~wiCcLbMNi%r;dZ6?;$w%{Q9pA7@w}=2>39&vguM* z7_5s4crkP+#dHfRfTt>_j97tQT~Y5)lL-_F9}hq}GPxJk-LM4&{4{Z^qo`k_LW;7o z=vdcM>}1d(z?P{2Xitt~pmG~dt2%PVcnn}SJ!)Z=gU9sy<AYu zWBALg26^6|_vX(ZG`R)T9AN9^`-zHnCB!qS__9lk%9kSteCvYXRqqV9rh0Z~YY36x zo|n7$z(iWmG8>C=p=amgyDkUKOAr_*zlqwJ^_6dLZ>#6*S3Nt9KU4e8CZfs?C%w=K zD@iYdiUF953h4Pa^YoQ#uTq%HtYn`NYu zY=h!VAoMgq%IHhu3;97%Ali+Tgd`8R@vR2+Hu$m#5eI;bM}Ge<&QFOuYtIXaixpvs z_%{&2a6iDr!U{iEGN{mIGi*Ao1w_}=!@~xc@lM?q+|Fjl2RS)84+K;xZa}19($LVD z?wQorjzY>Y)6;GMeZ9W<{m!#ebR%;X2!;#a-yP5ItLnI8u>%U(Ac496Q+TC$e-tes z4u9e;^=|I&%)rd8xIUb_AceLU-gS!T7Ro2WfY0YDc!Yw2LJD@RigCxs+tGtxRZOow z-l%e>Dn?B11%gbHe?R~}6_t??BO~L`% zz7Pgibs-Z$hW{zfm`kdqnvh9(akk~d+ZDhqjb-HC)XJ-|k|H<&I@b;|7haQQHIm@^ zghIXWvEZJ6Z)&v4`(hFkgJ>m!Gk_6#oqc_>vH}3by9(VJvrC{DWvh~qeD*hs_5=U+ zV)XT68}=&Zcyk%##5Roie*1@~EwCZ`UEaUHo+(z_pc2Ddb>i>35N0D8HXpDSS_gMG zCM6|hw*erVR$^jZE#lt#L{^=wsyCglUW4dXPjz**ST-=a@a?vNQl0~xLaAK0XzJGw zzJR>e0mmx#i3ytgFF|v)mOdh)6pSbE9nWXrb?0zRSo@t1LEyl#x2K0~i~nbMV9#y7 zMVPa6p?b+b;Yn?7ES+qe-n5z8&3SUG4FAxRiDbFlOkk#g&v|aqf zU<{4y zxsuG=e{KE8NbdWo{V0vvy{_IpPZWz~ncs88{C8DiQ0Gjk*6Uk02coY1YcYX}xA1f-T@Jd1NdqKXre7y2Hqz;K=g0Dl2Ci`oDQ z{|h4+Q1*LtLn|?K?|?a2wIm=4zStPD)e9e z0sN#N#2+7!Et{MW@q%$EX1)T6d0}szLm`>nAt5X40huAwKHLQ4Yy;f{GaYY0Gv-ya zLytua4`4;p-uU&#@BRn)WyznYiv*^T@D%PlUvJxrgDSz+&G{Dy$*okcegERVR4A{i zs`3T3`R32;WJ=C%d+x^pUbc!Zl z5+EZ0H@i4;{Sre;oBqj@CyrqJ{E3f?`}^uj+gXHsfZtAh7!$=nlTHuLZ-1;l_e_F-57up6Aq0 zBflhNXH!$+_Gf~xQWgX{2u_k^GZ5=4^}v3osK@jGiOCTr#gu9dMFrL61lBE)MN5Ia zDqEhXQxyh$maAQ#sLHk9szKTy(qWgX_{IO9gro)>Y2kn9*3HA?rT_?8U=$sK;KVVI zfwFR3xAA%tRHX=Nl#4Dhz!O?=b>N8FhynBq)P2K+&8H8*c3!czu;9^_$IkDh%J9Ik%@6B^p%Ek~JCX+}zyT z&imgBDw20ozzFL?!6Gr__x{bM5zEleiEYnopbv=Y&wq>E0mrVWRpzk>sqo09|7xYhO?lfw4DKs38Iz+>I1WVon6?{*{U|wE07e$6a z^&&TT4@~yakdP2^?Cxq}IZ>eg)_s=vjC({w@Blu$&(U`JeGuS*Uwo;GW`RM(+|ELx zbGLOokSnkogj+zJd7K5Go}QM12*`0ZkYr(`_>Bukwm{XVSJ%*}Q$6&yORlyy?n{F0 zv@n;t^2El*Hh|W2PTcRjyoEpl@c==!4@|_3-s`r@2?Zq3f7{6!meN@g2udXdg{Y~i zpAgJ-?Sat;M*6Y5Ko+7j2H0IsJ;4rsOXRfxTi4U(2`HzOeQyuVgNSa2C!k8D=L8Qx zSv~}+;%}kN`>3uiQAXh2QZpDa4jUop{~R$u5^V*+yjE~dVQk2h&}YQ1;nggd_;3Ab zQW)wOBV{bocpdgvKxpIl+S-~DXy@wjrev9e7I%L@#?c+@>S!b&KKlH)Xv-Pn8#hqp zbJ-ji(XaUGt4H=Pp8@!_8n^{$#g;lO{cof$^;~VuUP4R2i)vhIeqW@aN0tcM(scCe zhbHCkMmB<75oBEJiC}QO7#tnF76iK`LwU>NG9`s9FgSP}xI4on?1oL~3{)-($Y0#| zCM->Whc#8pZwW?Sjm2Qxso}4DJI~0JYT-!%JR%C=cM(lR#EM|DUeGAaO0- z4oaZ^_u*W(@LO$OF+99y&p`k3GXb(~m4+7=zR5FSV#NXjVkMD5UAJO}3y6yk2n=;k zwa|4L=+*%&IrDXNJmzs99<||ls0Tr$Ib_u!qMQ^E1v7CF6Z@@SJHaMR5%K2Dv{2-Vq|(84EIyg3SXc%fATKX) z!mLfXX!3F+`ZaDc0#U2W){sVMXedDB=AotEFR#P0@*II1X4vVQc?7;FowA>*)9=w2 zGm;#ne6E2?PcIOKrQ!8XULF&O@w@k613r@?*LpqlL*t(%HmIkkN8Lid3mha3g{+<4 zLwmC+!Bzkr;{P>B)g+cLY=> zD{1g zIzR}3I_;8)#VMIC(69MPH2TJ$?UR^y7Ac>~YN7#)T1{?J%a% z3(lvJpxN}da!0v2a)qOGp&%n8{{=^R3Lyr>QF~tMd}s@T!{JaiNb&KpjJlMSYlJa? z)FC(o~h|#$876wIphQ=r-#lVoU#iXk`O>+pszgL zFROAK92{hJuBsOoxHk~AY1Y6Hl|KqQ0i#VHXNY|t*`yUH^|Xa&U?PGOGG!JYhlhID z5{;{<5HV8ETc3iSXMBZsAy8bUO}A8$DK0MO#Hs=Ey&f-DgV^NI*^_Etc8 zm|m58ea5jyH%j)CQY03zqm3*UOBOl0K~{Z^{Jmf%jE!ya#kfnDcm@*u9vqa?I9_i5 zQyOA<%(3{Bm?ySln?Rb>(K)m4XY!iGfr{QLkblqggu zmYWC5>dbXbgiw3QpErZOiv~tzW?o+2wk=QESK^o6T2sP|?k`@vzya$L1Emw)Bd4US z{LtOsFEay~ai_+_#^NIdJq6LTHwwX~AEhuv=;@JwKMWb(nt$~1iOtOPG04LuNmSzv z{fzAg-~&1Ecuhf`{_ZOs#ZD1I+@;{?#VH5_g1DAE$sgc59j&wH=Hx(N9W;gY5CjlV zX#{;n&ZbL`m#3%J$ml4?G=AB17?{)O{;Dtpl8PC;=c2A4d$rv8@z$ju73b-XNgE!A z2iwCuKW{IunNO^BhHBZB#_grENxf!gs&RD|Mp4LO=&FmJtrL3k6U`!3|WkU(-@IYz4a9 z5u!n#$8G-p!@L|&3YJcA0Rf@d+y6GFz7va3;>si`b`n3yTecdKSVe$?EFUpK($rjJ zvR+sr991W&e&4B3$~2o8CNBeI2W}SCq=YFE*5pQR2^)=1>3xt6YHlqwsG&{BrB$60 zD6W_l8?jzck?32^hSfAAlicc6NrR5EH7yttDdN^&bLr*dD!>`t$0q2Fj#K>+u}2Rw zmS8~Bvun`LaeZpu$(>{>4JIEV)C$vKZen#~Eh^$rYAwJhDTKU{b#Tiy5>eQ)b~G&i zG6^P&t&S%BGH6CO!oVDU2ErJ?z_90FcxXdBBOTeUTa`b)z{z@rQUlxn7%_4C%=rCv z1Tc$mFn!PD1&BPdb{^d(b9kPX36n9(CKYOl4=WNSF?>s$KKfAyg`1MaBdfB(2e^~g z7#QyQSjL}z?mlZ*5AgK#9JArcR6WCcS%NLiG&`D%_bBdfDWT?e=gN@QPy*!fR%TI@ zgbl9$hVY$ft;o+mv2tj!Ep9FVKhTlIaBt_bSoF6P!@~2hx(}1hQmhOkw;+bV!HGSI z-?hhmtQ5dnWr}B^-Z;!KN-A`WM5FczqsxS|%Z6trkkz@4SS9u)Nuh-F6oHK3-PE^4 zQ-|)!G46nG5OA#g5gX|?7a-qY*7pPsuEYs8BuXEjFgE~htyX2+e&q2rZ)V~;ba;Y| z-Yf+Y4rHaa3)$FoaWspywqI-m=hyxO+#F= zZ+kJfdfD`C>SI$CK3w+!Xq^}y9X(oX0UsRaF2jEDpSr)jI*NdmpIwHd5yKq!Y%@-; zmKR#$)eJacI#>rF=iDP+R{p z-Ey$OK~8-=I%`i5bTRMj?DX?%I;U-s>%?q~sGw}Hm(UR3mP*L4;e`CDD6)IOKv z`Atpy2yjmGz6c_sWaCpYXR9+*C@sdfk=~lMDemysKNe13t3IS<)MeDK30;EOJi0ei zkq!=SV4bgjl`Kouie2&pIr>0wmi7zKa__Z>c0}1#@;FH#9iY<<0Q5z53r^pmfV4J& z189<%#>U1KB^9vDJz-WpBnr82I^i?r&Q7z#4o&MJHDoHpf};JRPB>rPTr) zTI(N+d_hM?CwOpmSN(5eEOq*I+Hl5-074oBg4W|my~oI|1DKhj*-tPq$bs-0KLkA2t-RUdoBZ`(9gbueZYnF zt3n6jO+PXpdAh*mN~u~}^k|*W7`!v0nV%KS^DRZvIr>is;qo0Z?WL4%;pAT2ATJ$e zr3Pnr|d08Rq$pdllpgA+H4GD()+c@IZozpaxV@v5~6zaNL1={QsYdXx(8AOmz7 zRFqwy~8IW zR`3Z6`bal`9f(l;?*w#mR|Ys#jLwp{4>L^6?6I5+*i8-ot`(MBi;y6h;I_0@$~f&0 zfpfTCRc+_;uS(>#T>l||pL4$#O{HaHy~(BcUj9O+JXaBwa}?&glF^RnR{SasJxgRRm7dfNzbUS$;Qo*B%7G^+#`jT5(`TqroKnBIw^DX)b%x>kVX~b5g^g z*Y@0A?D(o~Q5&U-AVPEtGH=~LAqZqpNJ7rz_lpWPx$^?T8xaY~3_kKV$;kBF@@+SH zKW#JfBX$#msWOHC?#lo!ssnPLI=UE|{9UpOh_O9di&Oo77U0vk4KgGQl!1_l2p*sp z`Qm@Wv=vmgwNn(B?94H_(*elL8RV3FJohFFrS=LzIBwUl!A=V&fz79oPT|lV)Zi#U zfbJ55Eu?Jnf2{b6-_|nw2!z@N%^W#lcmE?IuVX8CV83q&wJ1wjv`YUWUCFv>0XG~EsRR8b3k3claW&DawZJ#{ce-?t{_g z(p?tf4HAmdAUX5|^qRM@qvhuf7>rsbe~BleC$&i^3Ln2r7IFe~|3uX=JyB+lPQuLK z&F~Kv)kEg{+#i0Fmi%0Uia9s!ts_Dw!p0hWga}chxzC zNApaGVFBaQ{wT-hpBLnJgX%&EDj0G(7mNH5TOya!tmPe>CU5no@HHj(;k4)or2}zZ zem`WATOiUh>HXX%{{$bQBW<_H2B}=?ykpv;6O(*ykk)(8^(T2?-oqfI0K&rd@5-d)XxNdu1k5ME~z(9-7swX{8x(GZ2;#iX%Kh$N94`zP;sF)+``>A4z& zR9l7?KZJ4w1t12(@N@!L`Q;oj!iQNtLt1H9YRbqiq&%vQX&@ab2gKYkcJd^Q9Tk2TxY%doMtW`slsy;yhLf`i$xqT6TiJrR|C;8krqGg!N+Dt? zHp)CdezXf&YA9&xEC#=AobR@R6<{PMJ~2 zWm7gA=%#IGx9e3dqX~8rA7>mJub=WenLJ5gpB_vYCt-DX3%Z9!dwaV8OlazX+DvOk z%!U26QmFY}7)RPAaEj6ZvoxM6hC)=+uGiK zwLe?4aR;=(KZ7(V2G1-&YFy$aKsaMSm+u2X)iKA?Eoo(_6kJ4Le_tQ_v|Yna?xEx+ zZmN8jInc@PT&k}h-{C7Hp@242-V02NJ{QXVK^n4y;GjfN+$2j5-~*y|p7l{=*RYkT zi?Yx8pKTg{_~#K4c4jtlnfFaOPXqG*$iMA--2NZr2 zShvSLN(WT6rJ#e^f`Ei1N*WrPkBIQAhupWA&5&Oo=c$NpE-j6qjctXXG#_T)4AY~i zoJADa|E@9Z@9ljED4;L&eCGtYT%LuC1>x^V;0pIaQB4(SdE zK6dzNBZdJ0IyNjE`F<->;T-Tp(It~!=eVSr)m5tt_*#dEW!JJCr_lf7{4lWgGk8Qqbf-X_>lNvK%*{=*IOSDL zL+uwrss4tB+cRWkWi`?6OwRIKraj{pms5*nC|U0ET9Ug4RR!;&x?{~|H{g=#GNgUH zlSXV_z5xU18Niw)%BqQEH$?C{W@rB)56kqpftc><>N1(Cw5_)6j%MM_8E)G~}1 z9vmF>238_HEhUBE|3g&3`t}AO`Fmth(L5fx$V{|LY*8VSy6?x2AAxFG=qiCGAK!G*6?0)q4O(VX3n z#KAdmp;UW$dd~0t`-f@}mzJgnZNRqLOJ*yZCvt0u)nH*k-!UwXChK&Xb)Qa-kFPp{T~H5m-sRHf=AR$X!)&^|mHO1pUME*dhT#qcf;SG; z!OX^10wDHfX+c5399+KwK2ghUOD6Bi_)Db60TX{>;ma0~{s13gojAzwiu#G4paRZlkcbWcriB(BL#bN9Bk zwP8|(vw*FDYp)4-tcL(|Qy_kTOebWxE4{GeuXU?<)QPylEy;x9?DBc1im&pqRJa+j(w0%gabDddbq!Dw>&qe3D#uZ{9o3h z&;llczJ(5xK~7%Yy%EIj7k|MIp01Fy`$mK&_wOhmvYlY{*oFsU9_V@3QP$oMydJF2 zp`1g}vMqu(u{Z<9k0y;tmiJc<54dZ87HG8=fLf#vsLqgtgfRjb7=3@OH5@?#RU~lC zzuqLt4tC{YWP(TLA9{ISf#g%{K1)4z;YhNbAoT}`Dmm*^O%cAZ7f!)uUs;NKXeX;M z!MWnS(qFCko<;T_H?a&j=SB(XBx+vj>FGJ}@|INT7mdys@oR(2QxLd%9L8qg2_|^JOD_(f;#hsmmcDvP7VfTpOZkrCCxjym&*^9}$O1U2K`{w( z=`2(nXAs(ySz%AXfb3NXf3t`_3{edt6_oIfz z_*YX0D4l9Qy1O;QzYGI&gih-iv@Cy0O|&34ak;fcbR?v={kt~u=TGXNYYkz=Z`Ow7 zw>LL8Pk;n?ks!o~?@Zb^qzx>kH>7-B8G(XuXyeDPUpLkA%fYI4Fa<@~9*6)9(x*i# zph&s^2zdYAz+MoDU!Hw~MVI7bJGjP#k(n)z*;V?MT zbnb&h$KKHJcg^hVY=V3GSXdWxI&3iO!EE_WC~~Wle}??EEc&bmuYiHsR|mDasMl$Q z5nfA=z^VX%t&QduKf+A`VM>GQk%(BJF8S_`L3V{8R z547S{a1zHPEopA>6ShGkW#w_SMLPw4_iw=ay#&r(>n>DP;P6P+HBs1ZxijRFJ)Go) zzt%`dND$J}(vCDQlvGt4PeC2CAq|dmKTyA#!+Dd7$5ZMH@I@PlEv654ch}nZ2-)H~ ztSEZ+8uoynXsfdS<3ak*$y^QF#TergsPZ0Hf?Ftj!{zM|XrL&6H@+Q1x)YxY+$e1S zy9R4(2g%d2PZ&*s4O6Tm?GoOJ0#ln|Gr$6;8DAegHm-szKs z|Bj`KWoi%n&DgozZ+|$Q$s2u)x&-x5i=D6;Xyxo)yjbagjcqptM{Wohyw)GzDCR(b@8LZR^&`Zv zueWloCz-D$jMzwC3_n&c3ihG?tS%ozBf7G(k}_IsboTSjn9cjd?(FOg54!hrYU*t0 z6>LI5bFa==Jtup6`$hOW-th?u)!*vtr`$kFaJjs^Opfkk{TVu)&5#rSwzhhblauelSC`U$^5njpGY|CIo0!BBj!`S_E3hr;MBH{v zF#UdqZ-4so<;$u#d`K}=h9cKmLrozeA*Sm?i!yioR-OH=8)WjZ_;!Wb_#Od!r>~z} zpPfDb2Rx#Uj<6Qh{7X|v<^9RIbjkX_w|JlKL%ugWYFFP>rx57e$Khgffh1dkxUFAz zDF`G*L~zqr+zUreAyKLEFyq@?T46jLEs379U!`^g7NZaqiWw{Pq7 zva(tn?mxrRz$U2LeIDZ1%p$3tEQkjf(UN+qNa+Q!&vDy52q@6?f7FUO`|8yzGx*J& zz(Fe&q=^|7E0FD~!c>Get&)R5u{gCE-)nLB_wU~+bQZ|~zZktP$96jL_m7!m!Sne` z$e+L|swPYOT!v6bvZk9DMB~p7TrBbWOgt~2XegV>Lux>u#lgj8;N5$-T4LEzgcY6$ zc!)B6ZxXH7)5LNaqR4R{p)!y%Ha46fc*nUqtZtG#17Pv0!@m0MBmEaBRG2B$$q$N( ziazv#mha{#HeJR5Og@`}h!E=7ZgZ)EBl+tS@8xe|IhEq1;`j=4ajhpqo8bL%&}!bC z_}%8#*5xL&UC*9Bjn~#rQ&U&}z`@IVW#R38SqEf)G5CoWX+oRD@z6X&hTW_yl!d2=MFwOcRyF z(s=w#sfwss2tvZJF;c9mYPagve~ym29J@B1{ZY5EwLQbF5|}jMvuZkO+`iysWnC5? zlwvjRT-X(~1Cd^QON*>{*P9pPCNks^H?*%CdZ!=5i0H0qX}MfTCO?RPEDf~iYMsAu zuV3G2<%CYs$Dn0IPdN4(=z(ez}sE@p! z`3K9^Pq+6wW6)w_Hni&c=@w7bJ(_IVbU{E@`K+q(LCS3uu4)M2j}VVTCTAW+v;JaKJFam_2VaKqge z7Z*R0Q&N_E2oLAVWk-pplMy0{8xQr}8mHR^B=&xMn4FqY6zYTInPGH%sU%oCxPUsx z~uOD9UXlF65Fr6LWVQC zJm#nVh+lE<&NH<~RhXm|<>aU+@9OWrET8bCY~$mf^N%nuW9Q(QQ_qmP=z%UjLpO7t zd+wE#wnospl`j5&|0zB|OC94p;CpY`TUpiQ6&7-_^I;>%rTO@Fs?|aN;tob3Qb#M%FNts;UrLY&7=+=7kmbvd~_rE{X8y;>rg9v4_|#-+`5Yv2}=t{JDO>^i8(W zm>A4PMY`){6Ly;~U%q^n4q*Ha=v|1O=;{iK(hy~Y@y3};9HNt77EsE{^kJc)PwzxV z<1%*@UP$ur5J3v+CTIpP`$3C6iII4-l_(dlnvw)}(YWrc0u10s7eM=5ZMTQs6dc$y z8`^hEcdf3hY~1N)%h)h~s;l3qrdqRK&WXkmtRZMYFD)U#RS_1pjgb*898y>zZAdMK zSv?gZXx>0U1pFJ03TsSZW#z#SU>atQ&t|T^m3;bS{RnAQfzez+CT|T%Z_6OUy-GDr zTs85_mFtExMo9_J6*N=N&{8yj93Rl;rUE z@h@H=AIgX?S#CB4x-m%O~yda9Ra=~Bfu|m z($dmOVb}O+xJfbZ1Y!yZ5lF0Ey%wVd`S}fc`k5oR#S*0e(lh~%U-CnqX$i|)i2{V~ zGl?)vu_ot5nwdsI$B-!c%Ce7ux8Z9xfQHvDFIdMNKT!w~Ws;f|4fXc)NL_-y@#e>o z%K+>cw?j9HN{~7>mOyF(+@2qC_;SCXY$$<|?J6cU)zEWiRu*;=KXMs`P!Ce1yli(w+)E$4o^_sad;(fJ0B z0K`LCS=k2~A*aVR&IyB7?XYbPs_iBOn)35sL^ZSc<4}@g6tExXd)Xd%G?q3roDa~_ z((XY5Kr2Svz)E3ZLBY6)h{$;OpcnP|-;7^^eP2MF+zFNUbO7cJ4b+8PCv_>w>f08r ze2s$SXw0|$siJ_g(Suel*U<69?vA?fF6J0Wn6@KBLr-LDlFd9lB|u=xW&C!tazr@g z<-1uf!X6^3uo8`8qV?^Xh4 `kPGGuU|L4CGI8lY!k$3V<(&mZ=vuiQ_1>{KXa9cXfFTd%-}Uu3 z=-eu?G_^6^Cr_T_E>CT&t{w|WNlh0FT3K=!#q57+KLSvztG}P;b**8@T?%EkSc8~A z`O-&ghD?7UUgx&d=aP~Pmh~eF?Hc@ny#REmoHu+F!TA|mXsiv^F~s_vuK^fAC+akh zC6sQrjnXWVvAaiBOMnOq4<8&J-d{&&qq!fu8pmq!NFuzPoOXSHPnVwyRE2PcJ1`c{ zL*q|LlCCb}9*!4)Z4(|Io}ik@HS$_mG7Jc*+n^A{f%fp520x|-Pr|w#46xM* zs({9C%oc<&rR{>^wyvnCNUh_kdJsOh7IVO;m7oF-B(%IzRaGrZbXCOoF!TaCJs%yN zkzRa(xUTv&0O!Xi%3oaV!bbfMMIc*usdu@JqHU4TtGu#xaL5Pi0mb3b(N$x9ekVrI zG6!_5ATbjy7+a_0ES0RBsn9Rdc5yjuhs#PUlj-x_h{B83kF;WdFH;VlSUNK7RT*N9 z!&_t1)0g)kpS5Lm%YBGWuHx64dDHQHcoFQ25(xHkiBx#ZKI1;;zkCczSO#&wk467Y(R6D5`Sa%uoSQy?UOTKGc!aCv z_hOSc)%xD-KYEB9aMR$+7zlyXSGh)G2T+BI5(H6`N@aWq4-FlJII;DI$hc$UoI!>= zcd`phOLqfN!)*mwcrENG%%9MJ~90wVXMj+`)c|?pTO*7FLUi2o075K zXAN#nl)jB*@@s(XJG>7Ktxd^WJN}B9$CE?iBf4QU)O251xYbU$#DZ#B-T$5e^$l@S zoL_(bc>OftlaRZ^>=$^Po=*2MFK_yh<}hpeO0FKsTeg2K2<0MH_Uk4X1A9tC{ste&9B8yq7P6QBv|E z55Dz*8FJ!@s6R66+{aG%HbSL#IoUR^qOx+tj@J&BFP^OwJq#6Z@L7SQbEfg*F#rT;m&!@*A^BCv8%UzwL#&aRd(j| z4g>qGa6QNP1(BxXJPkU+Ha`23vBLN+h8F>`c21thFJ4)@|ELk9vd6OH?yb|;*FQuY zN99=qyng=R{lZojJ12}ae1w?Ed5Zlgyy}nTT2%O1lLYN=%$|;JSDs69_zC_b;ojr+ z6Z%g-I9MoflB!f=>vns{orVt>Fp9i)^uo$_%)KyR#IU9z9GKwMVPi z{M{+FK0kj26LE&syMG69I}rO!pE#s#Fzlre7{il+uk(>KeK%- zrnC7oElhatNj`JglCjF23-p#rN(>w!9^sSk61Fk_6in-LGPDpmqQL4}w2Ri3PQwzY zMwB(-Z6_dV&eml>Zbu6OP8MGz`3d9>}I@X9-4;;yFjx?B3}?v2uE>W2Mjm;Ou{D}B=Zx~FP>KE%38+RPm|9T1Crrb zYp96P)rs^9`l#(>ePDLI(}^P3^jl{cH|-r!d1#npdzWnHMYb?vUyXgov~&LHL~2$@ z=4o?{OZ-0Km<^C}yiTKY=(u71rYK$@&7_nDBV0O9r_ddikH^$C9K@4M#vUfrQo#)7&J2QKJ^gJXPh)k=F4}+#d)`i`ZNF5GT)me`cqVVyD3EjR z-{_lNALQ~#3_L6uQN-YEqTmY3IuV4spQl26(5|;Ydsupa#fG8zgC@f z)DVQoigGbisSM2Eq$4Okx%<-duXp}$KnyK3h#=C-G`L`g!o)pZwvmB+BG}@(eX#Z6+zD^Zw8yc#;Cb2Q-WaU5Bwd#Q09`zK$%uC zZamkS5O{BWdfHeFkZ9e6-Zwp)F4ZKguC;p4zjDVc_L}PidhyDxCg5M*skb9Hr&}1Y zbH(0?;&X6!56GPSh=s3;6MHs0h|mul2y0F9f?E^^6ogT7UVTV#a6if7mlA42=crvQ z_lWCS^<;5@3bH#hjJTKgu!tOmBA;Lj7wFE*j2uyMcHAiqE5|TMrDLt(1GF(0*qj)+ zTSw32XQ_$%v{Y9Uw8~tuqAYwmSP2ow_k1ZWVta1mS7P|9UuE;x-7JuGUPYc0HK#gm ze>WG%f}*zqop-nq&yzHNzJX`h^`aVl%%!-ru|}wW-$t`%o1_eFPpH0MLwGZGY4e2I zItZ@}k0+?buE6@GC<)=cKr6r*D zyp?3aqLVz^d>b!VyIMu#$<5KuSUlCC)YwJ7Qu3FYHLlPvs7-7hLjD(}^z-Ve6u2ck zhD)>fSOW3Q7>%-J$~WM5xj#Q75&dqkbLD_2QErw)^${qUy?BtRYr|Q$?@1>^>wEiQ z=DVB-pEqyb#H!^RXzJ^GIDi5_r){p_A{oK0$7IL;py^mrbI0den|*F7zyFWxv-ud+ zyCm%7-GpS?%_apF5s!-IUy~*&^NK!4p0gTe8H=H9jgE5t^E4 zfI6#6eeh660TvnunHf!;D|_87;=IR(up%wu+6!BrEy~i ziX0>GwCBE(vN&2J60wjm2}or&jgn3z+554_u;)9#;yw%{-;XhFuZQek=WZ>hw9 zJN`2;arar8NeA>1YY5?>M`ZyR6X2UYhDf>`FuI>t0y2)U$Y8o6_wWATJSg}QZD{F- zCVLCG$gxd`y@NNTdLbRfhHfT@~05t0&m!OC;_uwXDVhGrh)2hI*IPr$ZH;Yc?46y)XQr{U)_ z7cx%OU9y?(T6jVN^VtoVnR5*k+mqRo0Qq91?pdCmb&Bu>1-7Q*yd~2~R zZ$ulZLNH!hVvn+8CkT#deCBhb3LXSsu6_B4jZtb!imlh-#0v+<`af^*TTjW6qwMjC z85vDHY-}sJ(pM(~ne6yLa|VytT%g~BK#Us`t$Rl9Aa%3(CN6)l)G(OOBLSFU0BHeC zQ5Vpf$DuPNT_6rSho;kuabrk>{kHX==g38Kb8|8taA4X)b^Py-{QwOWl?gn*do+?B z+Liqco`C!^val@80`Fn(=hMd*y;H)daZmIs!w3pMWgk6l?fqGRU2m0)g+tyR+EykG z^Yk8O;Mg6@-{xQbyBz@lkkc>K`!A>Q&j@qNb+4^ne$q9iqYNyWpPw&rKq>bHQ(HJ?Ph(9Mmi7+qVZNCPJa{ z6QOzUq-vSQXNmz1c3a@PbU8mh>n6yLDo8x9Br}W!f5H~L>cQJ-vFk<=^y6oZFm$xp zR94q4Wth@lB!T_JjH`Bae^Wps-wV##<1ZycQ>& zzn5(-#=*n0H37@>3Br>H`HoKJ^VeF3YZ?qjW;uiJVC5fz8~YD8v#lY8_-Fy1tza?> zq~z6~o}CF{tQTI}!3Zvo5RD3d9HC+f{&nee5vO@fDD3I?r`;ANK7al!+3Na8?Wz9p zc?#lNxR2kDB|b%Z-}^`ju0$+7|BLq+G7tmU4}|E2K|nwN2W!k)*MQIE9yz`M71LYY zdweuKo=m|8UEn0W{J!>Diq$GwHXt1ThV~f3?L&3}M*7MJOgB=Q%81EFdndWK_?cqr z4n_^=w>CE$uRsgJM;%!M|Ihlh_80w5j%QPLRh<4ZDCOclL?VU>dGOxSrOu}$@@9L4 z1D`b6w~zT0^V z3~1icRsu<10f~VHnFr>;ZveBn5ne`yQAH5l%0na~J(U?YpLL$<8Jh-dVLDRzKD2pp zN3Ww1F%E>ZEgI!D2gS@9IAyJ@FW#DnV4WA&Z#ko_!^#cD4rxDBT1asHhM5_!Z>1n+ z#}EQo{ew4g4Yf%!lQ9{vn?tDnBxv+mw#E#P!i4Y^02z8|myN`sJ5xw)bO@oVSQ<3J zx0&wT5isHz6Q}8%FxQU268P`41wPr!DwD(!Lu|x9({XoC)OhNfh*9<%+LVaoGDd$Vw zZszpk(h!hmc%xfY1?Xzh(5v^lQVTH!>Xd@vU;4y_wucjUk{;)NJXx^$+H80 zyG3l#K2?t2?jJqoz)xH9tk!vn78YzRPeS+_IATnJt5fg6a^0O?KuQqK5`B8d_x8{Z zf)UO?7Z$F|ACI{((E7D{$NnJk)Y!s_GWZewljlBX&kYs4_!qA{JWkmF!EnMT2u4VR z%{`}KmVG9sd2v%+qICUJetM5n{U0WAC*UplQu?+)BULsZKrA)B4bdo};wfL5lyp`L z7=)9CaLpUp;;iP$3Pjmz+=?$otG`w5-<~=C9*K#G$q&TqLx4qa4c_jwTq}j7yVktC zJYhVM#bB*nseJr-WeNn~@;d+;NP}L3o^(|2)1sd~Ypsp#%zp%LDy96H_sVVX3bhdi zICvWKuB@QD@CFCE76eUUIMN4Wj$2{)B;2oCM*fsOpCg_@GuRTPEz9g!8e}hoQwHu4 zmN!8GNX{;J>rgX?Q_}HV)cDC0*W`s7`?+M4I5}?C<>M%sXv{DSl9Z$*Q8QpfUjgo% z1P%T%O&eb+4551l`ufY|+{!;N&8ctz+UfeWcoTV!}Zo!!s|-;TzhyDzY6d3`AkwU`@H{D17-CL!KuMoeNojC244C`qkBm zm2%FDwy3Q{OS0ee&A>da+CR}C3jz_@9Oz45K})!J#K}7)cSBGT%EBA5KhI0X48HH3 z^F$B{=}wxUZU+-TDkW>i#+Lb1in(@ufJ}S2-Xi&<;rI&f;#5h-pY!K z1`hW}x2V(}b!nccQU>qwPiZgnSf-SaNpo{@KCrc2N4K6A#JEDcc*%6Q__Ex=wrUN? zS#tjq8C9}ba$kzro%ampA7ohZ^))UYW5104C>wn&qDYGBv)mi-l$yDKn@A$~F$6)Q zF({S0_mr!khuQCpA5l*xtV81~$+=8WFQYR_Mj@*FRrWuvjTy>zq;W?rH{B=1B`!k; z;6F@E3$Ne2IVchcU{M;37SC7;rG1PwHfextCjUZ3QsyT}b4@5z;+{YNjkXM9qk=Oy z*E`{FDpB>DHYmCkpiaC}Bfh9(?}XYF|MBO_VL>dZ-mp__IG zc6R22r~5h`L740IIRyCy>}D(QbVl7I(%Yzv>fXibabHV__2+O3b!=YR4#uAk_atf1 z!HbgcBMT3f(%PCVKzJwTZNqa%VSRn-xJHPb>C&)qd1~>h9G7TY8B3ROAlCY(3m7V`)Cg8F{nAxPk^c7=gLOvdsLnXTQ~$YpXX zzL{FPJ!AQrxnqKX<6lKU1`K*uyLNg*`IOVJ6KjJMD{=_;2QOv!nSk$$6Xd z;#kz-)f{t){MJsk$tB6{TkO^qvHm%F-SUFEnGsy#<~t+As3osV|Jyd$x*gXvnKW)y zwpug)Rpi7NW6?WRx}b>r>m0p&nPf8JT6jF|MqZTgc-$m`oZHO3;Mo!l#>uvCbBCjn zyBo?b5K|OCCiXdtg1p>wk)+tieEd-b*J+#CzvwzL4Ik9lpok3b$_o`BUI-;%tRdOE z*}|Njm(}u7(GEgQe9+yjoE&2Kevw3Egj0i(*x178a?_9e%WV#gV){=Ck{r4!9P#h) z5%}y@-%!3$A)5@oNdbzhClLwq$KR3zk9I3Uf=;EGgZv0&c84d&2l0C_wF6%mn-cl@ zlw`<&IjF@+hx|dU{3 zJ?m|medZd-l+TeQ;dl$#a>d1S*(C6_7$<3G#^s!sj+e=Zjgl-0UV(~Gl2?-}eqiGN EKVH2_NB{r; literal 0 HcmV?d00001 diff --git a/doc/img/edoxy.css b/doc/img/edoxy.css new file mode 100755 index 0000000..616a0c5 --- /dev/null +++ b/doc/img/edoxy.css @@ -0,0 +1,966 @@ +/* + * This file contain a custom doxygen style to match e.org graphics + */ + + + +/* BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Geneva, Arial, Helvetica, sans-serif; +}*/ +BODY, TD { + font-size: 12px; +} +H1 { + text-align: center; + font-size: 160%; +} +H2 { + font-size: 120%; +} +H3 { + font-size: 100%; +} +CAPTION { + font-weight: bold +} +DIV.qindex { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navpath { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { + text-decoration: none; + background-color: #6666cc; + color: #ffffff +} +A.el { + text-decoration: none; + font-weight: bold +} +A.elRef { + font-weight: bold +} +A.code:link { + text-decoration: none; + font-weight: normal; + color: #0000FF +} +A.code:visited { + text-decoration: none; + font-weight: normal; + color: #0000FF +} +A.codeRef:link { + font-weight: normal; + color: #0000FF +} +A.codeRef:visited { + font-weight: normal; + color: #0000FF +} +A:hover, A:visited:hover { + text-decoration: none; + /* background-color: #f2f2ff; */ + color: #000055; +} +A.anchor { + color: #000; +} +DL.el { + margin-left: -1cm +} +.fragment { + font-family: monospace, fixed; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px +} + +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { + margin-left: 16px; + font-style: italic; + font-size: 90% +} +/*BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +}*/ +TD.indexkey { + background-color: #e8eef2; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #e8eef2; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { + text-align: center; +} +IMG.formulaDsp { +} +IMG.formulaInl { + vertical-align: middle; +} +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +SPAN.vhdldigit { color: #ff00ff } +SPAN.vhdlchar { color: #000000 } +SPAN.vhdlkeyword { color: #700070 } +SPAN.vhdllogic { color: #ff0000 } + +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { + color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +TD.tiny { + font-size: 75%; +} +a { + color: #1A41A8; +} +a:visited { + color: #2A3798; +} +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} +TH.dirtab { + background: #e8eef2; + font-weight: bold; +} +HR { + height: 1px; + border: none; + border-top: 1px solid black; +} + +/* Style for detailed member documentation */ +.memtemplate { + font-size: 80%; + color: #606060; + font-weight: normal; + margin-left: 3px; +} +.memnav { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +.memitem { + padding: 4px; + background-color: #eef3f5; + border-width: 1px; + border-style: solid; + border-color: #dedeee; + -moz-border-radius: 8px 8px 8px 8px; +} +.memname { + white-space: nowrap; + font-weight: bold; +} +.memdoc{ + padding-left: 10px; +} +.memproto { + background-color: #d5e1e8; + width: 100%; + border-width: 1px; + border-style: solid; + border-color: #84b0c7; + font-weight: bold; + -moz-border-radius: 8px 8px 8px 8px; +} +.paramkey { + text-align: right; +} +.paramtype { + white-space: nowrap; +} +.paramname { + color: #602020; + font-style: italic; + white-space: nowrap; +} +/* End Styling for detailed member documentation */ + +/* for the tree view */ +.ftvtree { + font-family: sans-serif; + margin:0.5em; +} +/* these are for tree view when used as main index */ +.directory { + font-size: 9pt; + font-weight: bold; +} +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +/* The following two styles can be used to replace the root node title */ +/* with an image of your choice. Simply uncomment the next two styles, */ +/* specify the name of your image and be sure to set 'height' to the */ +/* proper pixel height of your image. */ + +/* .directory h3.swap { */ +/* height: 61px; */ +/* background-repeat: no-repeat; */ +/* background-image: url("yourimage.gif"); */ +/* } */ +/* .directory h3.swap span { */ +/* display: none; */ +/* } */ + +.directory > h3 { + margin-top: 0; +} +.directory p { + margin: 0px; + white-space: nowrap; +} +.directory div { + display: none; + margin: 0px; +} +.directory img { + vertical-align: -30%; +} +/* these are for tree view when not used as main index */ +.directory-alt { + font-size: 100%; + font-weight: bold; +} +.directory-alt h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} +.directory-alt > h3 { + margin-top: 0; +} +.directory-alt p { + margin: 0px; + white-space: nowrap; +} +.directory-alt div { + display: none; + margin: 0px; +} +.directory-alt img { + vertical-align: -30%; +} + +/* + * This file contain a custom doxygen style to match e.org graphics + */ + + + +/* BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Geneva, Arial, Helvetica, sans-serif; +}*/ +BODY, TD { + font-size: 12px; +} +H1 { + text-align: center; + font-size: 160%; +} +H2 { + font-size: 120%; +} +H3 { + font-size: 100%; +} +CAPTION { + font-weight: bold +} +DIV.qindex { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navpath { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { + text-decoration: none; + background-color: #6666cc; + color: #ffffff +} +A.el { + text-decoration: none; + font-weight: bold +} +A.elRef { + font-weight: bold +} +A.code:link { + text-decoration: none; + font-weight: normal; + color: #0000FF +} +A.code:visited { + text-decoration: none; + font-weight: normal; + color: #0000FF +} +A.codeRef:link { + font-weight: normal; + color: #0000FF +} +A.codeRef:visited { + font-weight: normal; + color: #0000FF +} +A:hover, A:visited:hover { + text-decoration: none; + /* background-color: #f2f2ff; */ + color: #000055; +} +A.anchor { + color: #000; +} +DL.el { + margin-left: -1cm +} +.fragment { + font-family: monospace, fixed; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px +} + +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { + margin-left: 16px; + font-style: italic; + font-size: 90% +} +/*BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +}*/ +TD.indexkey { + background-color: #e8eef2; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #e8eef2; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { + text-align: center; +} +IMG.formulaDsp { +} +IMG.formulaInl { + vertical-align: middle; +} +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +SPAN.vhdldigit { color: #ff00ff } +SPAN.vhdlchar { color: #000000 } +SPAN.vhdlkeyword { color: #700070 } +SPAN.vhdllogic { color: #ff0000 } + +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { + color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +TD.tiny { + font-size: 75%; +} +a { + color: #1A41A8; +} +a:visited { + color: #2A3798; +} +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} +TH.dirtab { + background: #e8eef2; + font-weight: bold; +} +HR { + height: 1px; + border: none; + border-top: 1px solid black; +} + +/* Style for detailed member documentation */ +.memtemplate { + font-size: 80%; + color: #606060; + font-weight: normal; + margin-left: 3px; +} +.memnav { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +.memitem { + padding: 4px; + background-color: #eef3f5; + border-width: 1px; + border-style: solid; + border-color: #dedeee; + -moz-border-radius: 8px 8px 8px 8px; +} +.memname { + white-space: nowrap; + font-weight: bold; +} +.memdoc{ + padding-left: 10px; +} +.memproto { + background-color: #d5e1e8; + width: 100%; + border-width: 1px; + border-style: solid; + border-color: #84b0c7; + font-weight: bold; + -moz-border-radius: 8px 8px 8px 8px; +} +.paramkey { + text-align: right; +} +.paramtype { + white-space: nowrap; +} +.paramname { + color: #602020; + font-style: italic; + white-space: nowrap; +} +/* End Styling for detailed member documentation */ + +/* for the tree view */ +.ftvtree { + font-family: sans-serif; + margin:0.5em; +} +/* these are for tree view when used as main index */ +.directory { + font-size: 9pt; + font-weight: bold; +} +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +/* The following two styles can be used to replace the root node title */ +/* with an image of your choice. Simply uncomment the next two styles, */ +/* specify the name of your image and be sure to set 'height' to the */ +/* proper pixel height of your image. */ + +/* .directory h3.swap { */ +/* height: 61px; */ +/* background-repeat: no-repeat; */ +/* background-image: url("yourimage.gif"); */ +/* } */ +/* .directory h3.swap span { */ +/* display: none; */ +/* } */ + +.directory > h3 { + margin-top: 0; +} +.directory p { + margin: 0px; + white-space: nowrap; +} +.directory div { + display: none; + margin: 0px; +} +.directory img { + vertical-align: -30%; +} +/* these are for tree view when not used as main index */ +.directory-alt { + font-size: 100%; + font-weight: bold; +} +.directory-alt h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} +.directory-alt > h3 { + margin-top: 0; +} +.directory-alt p { + margin: 0px; + white-space: nowrap; +} +.directory-alt div { + display: none; + margin: 0px; +} +.directory-alt img { + vertical-align: -30%; +} + diff --git a/doc/img/foot_bg.png b/doc/img/foot_bg.png new file mode 100755 index 0000000000000000000000000000000000000000..b24f3a48b4e076b88cf1e802b46087ffbb3fabd5 GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^j6iJ9!3HE1Qx}DR1d4;)ofy`glX(f`uqAoByD;nl zL8a%*b^=8>3p^r=85p>QL70(Y)*K0-AbW|YuPgga7CvEi%SZD}LFVdux;TbNTu#2R zIsJTn+kYTPulo1Ll3AD;2!xfDmD#wLvj}>v&@k-CVP=T_%(cphxuXQAk-^i|&t;uc GLK6Ub>Mc;VkfoEM{Qf z76xHPhFNnYfP(BLp1!W^H+WcuRXD>A=l%i;Wq7(chG?8W+i%Esz<`6f_y7NWHH!5o z63R1{^0cb0vMSkFaE_%x<+7O{*?Xs&Ff%xKT5jO&GtAqcqoa~}b>qg&H07ky z617wnX2HUfTT*8{k002J-1^@s6XaB>y00001b5ch_0Itp) z=>Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3Fc5TrKj#zpOzs?z2=A0p@aw&u*pMn|G)ug+?Vh;0+zHe5dVLoF=!DBW&zJ?E zp99|S_j0@4%Io#|xG+sqdB5NP{rn5Cj%O+78UIn|DpKcsK9>`B2V6JsOB3oD&r;4a z{-e%Sw9ela{A&{jdu5*U-Tgr1~ zQc-ZvZCmQQrCnTG+COg8zWQ3Lv1sjNIKQPlR|Xsq_}(oT0MbDS91lPg3>xeBFKokrh3I+f~!N36>5GNtP zFb=56FWNP#oK=?bNEQ~!rtXW9X1GX=k~FL`OjOeF$R)LGB-wAZi(5xddgID^{pUl5 z$!2zVWE!iC5c%CAFL=jfl{TW1M$7Wjcr9z}SyPKmlC20r0B}G6Q80PClsJ^eQ9Rdb zuHflIJ5saoBdvW)J5o7`LrQ$sb0li*FS@pt^@$vLe#kJ^<1ntHwKLacEE8!V_VYY{ z^jk0Fa-9o0ILfhhgnDcg*`~%yk#UNgFLkMLQ1xp&>oHLMt>=krgKLZ9aoj&)eVyWk z+VI9yb#%knV zBgOT1iW^1q->g9a$6utrxv^4Ql-s5#yS%xS5>LwpJyaYZ1w-06F426k%%gi2p;YTL zn*Zi$*TU&q<}Gq{z5F%GPa}Dt9$}k233)sorIb>h&nNZ+VE-)`LNtIN1b_p=0f8Pk zSwvore6GJZg3A%uh&UU`%8A$z3ApNcvGym`^9BW5y;mkO7OVYaI#wj=im2;bzSt*w z8j*3rXhhk-tiA%ik?Y6P7yM_$}>d^Cl%aa8a!%A!J=gv)gqCjA%RAmjShY zk&jin$jBj)wrhPzE#o_v^@kLW;DnK~k;Uxogc+{8mlL+=3tKP%4hR4$2Lynj z95C}RO)LJ$<@I?2i7h|tH#%lcU&}tk-(ol0<1_foFDdWsgqjV%=7cRA;M<%KLNw4f z2!R6vT{&RuTk7799C>JZ4;!>{ThW;;ZOYD_SA%VO2ZR&C3B68;Eg1NXEf@e0gaF^` zfS#=57JO;X{zkCF($|*uL^8|wn48N;fkQ7R9I3CpA0+QRH%LYRy5b)R!`g7p731Il O0000002J-1^@s6XaB>y00001b5ch_0Itp) z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOZ7 z02vXk7GypE01Qq^L_t(|+U;H2a^tuXlN0^d3_%Mmt|S*_xtkl^78E$bGzMsW@O^E@B1-+ z=cVS*V0UU7pRP@U;-OvwL>DMu{R0abUb{x*}m z@B4oYcs3YunesE)Z}j8zrzRR*2Qx`$S!kAh|3>CJWrAG*GLX2Fe)h(rzjg+&sxS80 zcbMC=ef;e}EdiJ(`3%q$9hv{=thAZ zpj~02U6We1r_3JuyTgdH571c<%rJWAn5)2<+gWe7+X22Y2-~(nHi`f1_)l)SMgf#Jj8JEL5q`z9;(>xI3~8m`p)OaYtLX&lh0g*>LDJVk86(i z=kyov4*{0}DZk>FF#wNa4hGB@`||R#3~-LWl@Egki#?GMP;Am(US5vA=z0`0WFWFJQh<&3f+l(2_hZcBJtII5vSC1p*H_JX1~&q0d?50; z9+i-IF}K_8xX5gx6*IWER<=amoW`jd#YBk4T_A$cGxKdSUi@`qKv&aoVEA{nDHR+_2yWJasfY5BO>R2DM#*|ftn40E*Ih_;(Ua&ul4 zh-X-Wv9g=*`;3Z+YsQ>oJK&jZ#~tem*arhL|A(2liun{cE3;aeebuf@K z<{@$WJbN5uKxH0Oawoia%4=cqI_8 z@atR?uKZ`Gy>$Q&W$P$}#1#?lnW*=w=zGSDRyFp{|IueF%YZXbRXH<9LGqa_H^Z!7wXo>3 z0MudBnQQ0*%}I+r0dV+$PEer|sA_fDtl!x6!Mf(HQlMPz{9mChbjxs8KNzZ?j@kVX zgyaHqPMa_gx$0w97CQr!*}zAspBlr?S!q5>pR8ll>^(m=-luk6H5 zDh7cN0W_QIN=oGd$WiU)+P0b)Cm_l9kc;^F`dn2}Y{MA~M;^u`amch*0t9wHNZg== zu^-YfqhOqGZk!l}q47e8q$++sBw10+s!U&gS}Jt~@;woIxD4j_gkumL)pBM4XDLGr z0+AwHS*WfFjbnr)S`}+4Kr$r_(h)Ap|28Mea;%P1kD_P?{qED|RA;X6o!p2zi#;p$ zR7)A$dpaW?=mrNJ?W2;dq2th8uWxT}%iG)A^85GiCw~o@(#&SezeC%6Ak)sycgkj& zQI%6)ol~t%QGK9ATuK92N!ne1u>(3MO~w2;<>x7LkNVBh{3jEfI~@ZaPl&oM1(LDX zjI*Ag3M|wruZ|)&uem_Jsro$rj`x;>Af}(p>SA>ton5Xf-%SBMUq1o}`mNO36}x6% z@u?J-pVqj@1^FS2$+8HMu~S^^l-WWplxI)0s)#6)sQOdx24gKZkaEnFYgUz_Tbb4T zV6c^RNXecVUrG9qkGO5yzdj&iKnFyX%v`O-je(Cku9B~-XuY$&nv;N^O$2ur!*}w2 zGr2vc7Ds@sa(WDi$~+%w7{@eJ;eWLtx&l{6ZIh$*D$(7Y9M*RAV7R$C_x-Go=a%do zU{wj_$|@kH{ZI)(QY;r>in&mpPURU{Uad3nPKu=pRMgs%%G_65ZOjH2-F8(U87S_y zB;BCHWzdx^*;AE?Gfby^M+N+uw90JRuUkc_62LP6R3KDr(=Det<+C%)Sp7cofR!2R zfUC3rN@Xgl6pdRptk}?DRkt)Y6GU`O>umpyFX!YVs|t?`z5{?NeUNj5SAZ~AL0I{! z+6JWS<2jM@%yx8DiE^fnJDY&6f}Jj)oCLFz%w~W-7%-+=DmJQ2Xom?ExLDe!5-4;{ zrkm2K7HoBZa5kdt_EkltGmO_U&FmUimcwBa*qpdhwWTf#XnrKCCYs)P=%?EVbX z&6;N?rQ$52ciGXc>^%8^c})lt3!ojU6wsW{6x%WLdM&yE11b~CQYGE=OeJ)<5VW9y=&YuLAfe%Wnt==upw4Z%rPz^ADi2AcH>mlm8?>U_3Y8dOv1O4 zV>yC_$}i0K5rw?y;c>RjW%Bt-w4gwQ9wxN=DQW{<|6zhrfWfx7jp>?kakty;!{leS zLyF(rcHRm&GiSWMthmlMu8QMIhR;~{3KOihaf^V-(k2Bu1pNFEDW46M<`DZaJs%S^ zD0d*@=!k*`5c6b5hGIcU25)3LBw|(ivMljO=4*%&BKQ=r)OKtvDn@MT1RK?Et|-`Z zTngovW)Lfrn~6iQc6^_S%FQ7vYp`wGvcA8+KV4jwNX7TrKgt6)CM|yXVU~0;m2AAZ z$b@<0Z8rGmxaun=DydnV@JcVpHWqhsglZT044iyETcyS}V2|@r$*~aQWf13kir_}T z&tv-(1*4o9(g#N0im7WEaGCfZABR?kjnAY1>8xN=B|ZdvM?TLa_y~M%WdcR~%>2gr zLP}&LG(~0^EeOl!xi#d7BiCFXL5M2Dv6Kv|TEri;YkLH7J|})weg8xTVYNQk*}F!q zVC(LK*AXzNh#8r$9N=|CqZv?WXN;MYjaqu39=c|yS9zjUX=T%jZs!oe`3P82x zoCIb8gsR3f`)rcc z&IiudZ)HD{0aMjs&nzpb#0-vh4&}`l=o~;fU~}GACC856SOSnmxRr2J`Gv?obbyLX zbru_-pRNQ;=?7<+PAQ1kmlLA2iOYnuz^eocGZAui%=-TRF25GkVKk*?VLM7WBGYPB zT*tpuphVY?L>99zcgqh{8?J&32Rv?+%)Z_WCB$d`hC#@mKYy$$hzm4z911e3T@BQE z6}a5Q^z2GI$3(jeiH2?d26Vp6Zr1N{77{V3le;970pcooz1rBP zTCCqm&A0&u`_5tKoG#cZcARCvr+{+b_xPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOZ8 z6%`IG`XD&~00I3;L_t(o!^Kz8j>8}fODg_+AF{uksuh}hxC0rJP`W$mkkHl^jB%XM z>f`Y+`Dtd>`gxwMmr`2KIk$cshdiH8N#}XW6$o}5WA?p%5)sKc%eHO9fR!#HlFUqU z&XQ6Z1~3DUmCHm#rjx?$lu|lm24QA+Eh4g2CJ}X<;QbGo;J_$CohD|s1Tu}z3KIrH zRtpQ8-Z|UyQP4caCB~&Z3QG0mMzcQLYIcQ!(sFW-xf9knF@|(?iY~XAOhHzd%#8OD2m>x}XSSsVf@;^obfpX48<@ZgFF$M4@xtjbM#B=Ojp!9yfFNKXj22K7STvD?00000NkvXXu0mjfB76)l literal 0 HcmV?d00001 diff --git a/doc/img/menu_bg_unsel.png b/doc/img/menu_bg_unsel.png new file mode 100755 index 0000000000000000000000000000000000000000..50e5fd8d3d17114bc71e14c483532f2c082920b2 GIT binary patch literal 1596 zcmV-C2E+M@P)002J-1^@s6XaB>y00001b5ch_0Itp) z=>Px#24YJ`L;wH)0002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOZ6 z5FZU~yaYY~00q2BL_t(|+U;H2a;q>5blUuRzqvD+7VvpFWE>%_)?7k5*?npguqAmd z8(5Uf*Vk7qf^ZV9(=;gx!g&NNrIcY9%E!ltq9Ht=fVI{#3`4nIuZo7C3@E%I0mpGH z+6xLIpzyv+um~ueb`dgXz*=j$TrP@=0TUO+Zl@)sQ3vT-lF8GjhNS)Y)Np5NBKI{~L@T3m#*2iTKp zt@p;JX@cbN4E2Ix|BjCFg536j+O}xz_u6Q`^V-S$v$poy&cxQ*Y0r;rMq}sMi^c@` z(Y9kbHGfVm!D!}MMH6RQOQ=PVd8HOe5K@dz0av&_)W-mG0@FVnX-$jszG6Cpd6iG4)S zD4R33W^wegr6p&!^ui1{3`424F0w(E#-nu32HZMgjcogm$jB1kn}usg#Vp4?lQGIP zmJDq6inbT557~swV%+wP_%pYAzYQ~vV>tL(hik9?P_~PVkL=oF50e?tN^s;oR77r% zlT|&VC}Ga0&tEJ%k7- zoJv4FMiNe2g8%YGh@d4{5VmDN2~q_u!NU6zP)o2N0s>_EwNi4;;4^G#zyC`L>8-YI zIsZ<;Sq-zMv%STs5t%X@*w0xZXGHX=S58L)URT4u^Pb?4-gC!@j zGZO+Nz0VPNkPS1cMpr9pK zPzLm{wVGyxy%obpDUi2TLEY1CBu?G4a_w4M*7W_50a2rjQkgL}dUVxOnilo5_XJ|? z^0b6KgUQ;2DyO!8Gi7vpi4|3GMVi2@-Nh0d2`yX4qE34Ty0;9h7ucR!#o2^lg6|D> zq>N@KDl1M!v148j=!p*!BwK!Xg({IeZ9%}cIAvzMSJ)Ae5UHkn2oMDWN!z_bn~X9f z@-5QES=A0wM|(C$1t(DkMz$~$G8#J+SMOZ5Dyv8A`w~27zqUXna*hph7O3bmD~Gp^ z*;fa=*%<}bla(WZrnkg+@^mC+kFs@kF8aj)Hk+cY4=Q!sYBVE3usz00Cd{g}$bgX+ zEs`2}PM|AlPwbhc>#U3~dKV?KArhvt%U4th9!;L?oeXA`K|g&EO%g=b=rg7ws`Z0W zfG^}&b8$*k*B4={a+xJocKjaIK(oCqTOT@;wzHCX)@Jr%Fnd8LdMj})ftln4_kht_ z?hOuGQ#w0_X^UxNi{yO`dG|z5aq*tmGIh6m-ucZ4$E=q33^;eTcR-I+1i!M{_!a$H z+wPGv{WJp#!l6$>RG?fqm4Ls$zapS;ZU)p6ES#PJ^<&F|2q=hvg78!V{`~xifWmnM uoCT@+p&H=~TxzX#9LMtc`Kf3KPscx4r4cOw-wj9r0000 + + + + diff --git a/eet.pc.in b/eet.pc.in index 669d03c..ee95887 100644 --- a/eet.pc.in +++ b/eet.pc.in @@ -6,6 +6,7 @@ includedir=@includedir@ Name: eet Description: Library for speedy data storage, retrieval, and compression Version: @VERSION@ +@pkgconfig_requires_private@: @requirements_pc_eet@ Libs: -L${libdir} -leet -Libs.private: -lz -ljpeg @fnmatch_libs@ @WIN32_LIBS@ -lm -Cflags: -I${includedir} +Libs.private: @requirements_libs_eet@ -lm +Cflags: -I${includedir}/eet-@VMAJ@ diff --git a/eet.spec.in b/eet.spec.in index 45bb9f1..5a91f60 100644 --- a/eet.spec.in +++ b/eet.spec.in @@ -1,12 +1,13 @@ +%{!?_rel:%{expand:%%global _rel 0.enl%{?dist}}} %define _missing_doc_files_terminate_build 0 Summary: Library for speedy data storage, retrieval, and compression. Name: @PACKAGE@ Version: @VERSION@ -Release: 0.%(date '+%Y%m%d') +Release: %{_rel} License: BSD Group: System Environment/Libraries -Source: %{name}-%{version}.tar.gz +Source: http://download.enlightenment.org/releases/%{name}-%{version}.tar.gz Packager: %{?_packager:%{_packager}}%{!?_packager:Michael Jennings } Vendor: %{?_vendorinfo:%{_vendorinfo}}%{!?_vendorinfo:The Enlightenment Project (http://www.enlightenment.org/)} Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}} @@ -15,7 +16,7 @@ BuildRequires: libjpeg-devel zlib-devel BuildRoot: %{_tmppath}/%{name}-%{version}-root %description -Eet is a tiny library designed to write an arbitary set of chunks of +Eet is a tiny library designed to write an arbitrary set of chunks of data to a file and optionally compress each chunk (very much like a zip file) and allow fast random-access reading of the file later on. It does not do zip as a zip itself has more complexity than is @@ -23,8 +24,8 @@ needed, and it was much simpler to implement this once here. It also can encode and decode data structures in memory, as well as image data for saving to eet files or sending across the network to -other machines, or just writing to arbitary files on the system. All -data is encoded in a platform independant way and can be written and +other machines, or just writing to arbitrary files on the system. All +data is encoded in a platform independent way and can be written and read by any architecture. %package devel @@ -69,6 +70,7 @@ test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT %{_includedir}/* %{_libdir}/*.a %{_libdir}/*.so +%{_datadir}/eet %{_libdir}/*.la %changelog diff --git a/m4/ac_attribute.m4 b/m4/ac_attribute.m4 new file mode 100644 index 0000000..23479a9 --- /dev/null +++ b/m4/ac_attribute.m4 @@ -0,0 +1,47 @@ +dnl Copyright (C) 2004-2008 Kim Woelders +dnl Copyright (C) 2008 Vincent Torri +dnl That code is public domain and can be freely used or copied. +dnl Originally snatched from somewhere... + +dnl Macro for checking if the compiler supports __attribute__ + +dnl Usage: AC_C___ATTRIBUTE__ +dnl call AC_DEFINE for HAVE___ATTRIBUTE__ and __UNUSED__ +dnl if the compiler supports __attribute__, HAVE___ATTRIBUTE__ is +dnl defined to 1 and __UNUSED__ is defined to __attribute__((unused)) +dnl otherwise, HAVE___ATTRIBUTE__ is not defined and __UNUSED__ is +dnl defined to nothing. + +AC_DEFUN([AC_C___ATTRIBUTE__], +[ + +AC_MSG_CHECKING([for __attribute__]) + +AC_CACHE_VAL([ac_cv___attribute__], + [AC_TRY_COMPILE( + [ +#include + +int func(int x); +int foo(int x __attribute__ ((unused))) +{ + exit(1); +} + ], + [], + [ac_cv___attribute__="yes"], + [ac_cv___attribute__="no"] + )]) + +AC_MSG_RESULT($ac_cv___attribute__) + +if test "x${ac_cv___attribute__}" = "xyes" ; then + AC_DEFINE([HAVE___ATTRIBUTE__], [1], [Define to 1 if your compiler has __attribute__]) + AC_DEFINE([__UNUSED__], [__attribute__((unused))], [Macro declaring a function argument to be unused]) + else + AC_DEFINE([__UNUSED__], [], [Macro declaring a function argument to be unused]) +fi + +]) + +dnl End of ac_attribute.m4 diff --git a/m4/ac_path_generic.m4 b/m4/ac_path_generic.m4 new file mode 100644 index 0000000..d427241 --- /dev/null +++ b/m4/ac_path_generic.m4 @@ -0,0 +1,137 @@ +dnl @synopsis AC_PATH_GENERIC(LIBRARY [, MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl +dnl Runs a LIBRARY-config script and defines LIBRARY_CFLAGS and LIBRARY_LIBS +dnl +dnl The script must support `--cflags' and `--libs' args. +dnl If MINIMUM-VERSION is specified, the script must also support the +dnl `--version' arg. +dnl If the `--with-library-[exec-]prefix' arguments to ./configure are given, +dnl it must also support `--prefix' and `--exec-prefix'. +dnl (In other words, it must be like gtk-config.) +dnl +dnl For example: +dnl +dnl AC_PATH_GENERIC(Foo, 1.0.0) +dnl +dnl would run `foo-config --version' and check that it is at least 1.0.0 +dnl +dnl If so, the following would then be defined: +dnl +dnl FOO_CFLAGS to `foo-config --cflags` +dnl FOO_LIBS to `foo-config --libs` +dnl +dnl At present there is no support for additional "MODULES" (see AM_PATH_GTK) +dnl (shamelessly stolen from gtk.m4 and then hacked around a fair amount) +dnl +dnl @author Angus Lees + +AC_DEFUN([AC_PATH_GENERIC], +[dnl +dnl we're going to need uppercase, lowercase and user-friendly versions of the +dnl string `LIBRARY' +pushdef([UP], translit([$1], [a-z], [A-Z]))dnl +pushdef([DOWN], translit([$1], [A-Z], [a-z]))dnl + +dnl +dnl Get the cflags and libraries from the LIBRARY-config script +dnl +AC_ARG_WITH(DOWN-prefix, + [ --with-]DOWN[-prefix=PFX Prefix where $1 is installed (optional)], + DOWN[]_config_prefix="$withval", DOWN[]_config_prefix="") +AC_ARG_WITH(DOWN-exec-prefix, + [ --with-]DOWN[-exec-prefix=PFX Exec prefix where $1 is installed (optional)], + DOWN[]_config_exec_prefix="$withval", DOWN[]_config_exec_prefix="") + + if test x$DOWN[]_config_exec_prefix != x ; then + DOWN[]_config_args="$DOWN[]_config_args --exec-prefix=$DOWN[]_config_exec_prefix" + if test x${UP[]_CONFIG+set} != xset ; then + UP[]_CONFIG=$DOWN[]_config_exec_prefix/bin/DOWN-config + fi + fi + if test x$DOWN[]_config_prefix != x ; then + DOWN[]_config_args="$DOWN[]_config_args --prefix=$DOWN[]_config_prefix" + if test x${UP[]_CONFIG+set} != xset ; then + UP[]_CONFIG=$DOWN[]_config_prefix/bin/DOWN-config + fi + fi + + AC_PATH_PROG(UP[]_CONFIG, DOWN-config, no) + ifelse([$2], , + AC_MSG_CHECKING(for $1), + AC_MSG_CHECKING(for $1 - version >= $2) + ) + no_[]DOWN="" + if test "$UP[]_CONFIG" = "no" ; then + no_[]DOWN=yes + else + UP[]_CFLAGS="`$UP[]_CONFIG $DOWN[]_config_args --cflags`" + UP[]_LIBS="`$UP[]_CONFIG $DOWN[]_config_args --libs`" + ifelse([$2], , ,[ + DOWN[]_config_major_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\).*/\1/'` + DOWN[]_config_minor_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\).*/\2/'` + DOWN[]_config_micro_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\).*/\3/'` + DOWN[]_wanted_major_version="regexp($2, [\<\([0-9]*\)], [\1])" + DOWN[]_wanted_minor_version="regexp($2, [\<\([0-9]*\)\.\([0-9]*\)], [\2])" + DOWN[]_wanted_micro_version="regexp($2, [\<\([0-9]*\).\([0-9]*\).\([0-9]*\)], [\3])" + + # Compare wanted version to what config script returned. + # If I knew what library was being run, i'd probably also compile + # a test program at this point (which also extracted and tested + # the version in some library-specific way) + if test "$DOWN[]_config_major_version" -lt \ + "$DOWN[]_wanted_major_version" \ + -o \( "$DOWN[]_config_major_version" -eq \ + "$DOWN[]_wanted_major_version" \ + -a "$DOWN[]_config_minor_version" -lt \ + "$DOWN[]_wanted_minor_version" \) \ + -o \( "$DOWN[]_config_major_version" -eq \ + "$DOWN[]_wanted_major_version" \ + -a "$DOWN[]_config_minor_version" -eq \ + "$DOWN[]_wanted_minor_version" \ + -a "$DOWN[]_config_micro_version" -lt \ + "$DOWN[]_wanted_micro_version" \) ; then + # older version found + no_[]DOWN=yes + echo -n "*** An old version of $1 " + echo -n "($DOWN[]_config_major_version" + echo -n ".$DOWN[]_config_minor_version" + echo ".$DOWN[]_config_micro_version) was found." + echo -n "*** You need a version of $1 newer than " + echo -n "$DOWN[]_wanted_major_version" + echo -n ".$DOWN[]_wanted_minor_version" + echo ".$DOWN[]_wanted_micro_version." + echo "***" + echo "*** If you have already installed a sufficiently new version, this error" + echo "*** probably means that the wrong copy of the DOWN-config shell script is" + echo "*** being found. The easiest way to fix this is to remove the old version" + echo "*** of $1, but you can also set the UP[]_CONFIG environment to point to the" + echo "*** correct copy of DOWN-config. (In this case, you will have to" + echo "*** modify your LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf" + echo "*** so that the correct libraries are found at run-time)" + fi + ]) + fi + if test "x$no_[]DOWN" = x ; then + AC_MSG_RESULT(yes) + ifelse([$3], , :, [$3]) + else + AC_MSG_RESULT(no) + if test "$UP[]_CONFIG" = "no" ; then + echo "*** The DOWN-config script installed by $1 could not be found" + echo "*** If $1 was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the UP[]_CONFIG environment variable to the" + echo "*** full path to DOWN-config." + fi + UP[]_CFLAGS="" + UP[]_LIBS="" + ifelse([$4], , :, [$4]) + fi + AC_SUBST(UP[]_CFLAGS) + AC_SUBST(UP[]_LIBS) + + popdef([UP]) + popdef([DOWN]) +]) diff --git a/m4/efl_binary.m4 b/m4/efl_binary.m4 new file mode 100644 index 0000000..fc2f200 --- /dev/null +++ b/m4/efl_binary.m4 @@ -0,0 +1,79 @@ +dnl Copyright (C) 2010 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that checks if a binary is built or not + +dnl Usage: EFL_ENABLE_BIN(binary) +dnl Call AC_SUBST(BINARY_PRG) (BINARY is the uppercase of binary, - being transformed into _) +dnl Define have_binary (- is transformed into _) +dnl Define conditional BUILD_BINARY (BINARY is the uppercase of binary, - being transformed into _) + +AC_DEFUN([EFL_ENABLE_BIN], +[ + +m4_pushdef([UP], m4_translit([[$1]], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWN], m4_translit([[$1]], [-A-Z], [_a-z]))dnl + +have_[]m4_defn([DOWN])="yes" + +dnl configure option + +AC_ARG_ENABLE([$1], + [AC_HELP_STRING([--disable-$1], [disable building of ]DOWN)], + [ + if test "x${enableval}" = "xyes" ; then + have_[]m4_defn([DOWN])="yes" + else + have_[]m4_defn([DOWN])="no" + fi + ]) + +AC_MSG_CHECKING([whether to build ]DOWN[ binary]) +AC_MSG_RESULT([$have_[]m4_defn([DOWN])]) + +if test "x$have_[]m4_defn([DOWN])" = "xyes"; then + UP[]_PRG=DOWN[${EXEEXT}] +fi + +AC_SUBST(UP[]_PRG) + +AM_CONDITIONAL(BUILD_[]UP, test "x$have_[]m4_defn([DOWN])" = "xyes") + +AS_IF([test "x$have_[]m4_defn([DOWN])" = "xyes"], [$2], [$3]) + +]) + +dnl Macro that specifies the binary to be used + +dnl Usage: EFL_WITH_BIN(binary, package, msg) +dnl Call AC_SUBST(BINARY_PRG) (BINARY is the uppercase of binary, - being transformed into _) +dnl Define with_binary (- is transformed into _) +dnl Define conditional BUILD_BINARY (BINARY is the uppercase of binary, - being transformed into _) + +AC_DEFUN([EFL_WITH_BIN], +[ + +m4_pushdef([UP], m4_translit([[$1]], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWN], m4_translit([[$1]], [-A-Z], [_a-z]))dnl + +AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +AC_MSG_NOTICE([$PKG_CONFIG]) + +with_[]m4_defn([DOWN])=m4_esyscmd($PKG_CONFIG --variable=prefix $2)/bin/m4_defn([DOWN]) + +dnl configure option + +AC_ARG_WITH([$1], + [AC_HELP_STRING([--with-$1-bin=PATH], [specify a specific path to ]DOWN)], + [ + with_[]m4_defn([DOWN])=$withval + _efl_msg="( explicitely set)" + ]) + +AC_MSG_NOTICE([$msg: ]m4_defn([DOWN])[$_efl_msg]) + +AC_SUBST(with_[]m4_defn([DOWN])) + +AS_IF([test "x$have_[]m4_defn([DOWN])" = "xyes"], [$4], [$5]) + +]) diff --git a/m4/efl_check_funcs.m4 b/m4/efl_check_funcs.m4 new file mode 100644 index 0000000..3714969 --- /dev/null +++ b/m4/efl_check_funcs.m4 @@ -0,0 +1,435 @@ +dnl Copyright (C) 2012 Vincent Torri +dnl This code is public domain and can be freely used or copied. + +dnl Macros that check functions availability for the EFL: + +dnl dirfd +dnl dladdr +dnl dlopen +dnl fnmatch +dnl iconv +dnl setxattr (an al.) +dnl shm_open + + +dnl _EFL_CHECK_FUNC_DIRFD is for internal use +dnl _EFL_CHECK_FUNC_DIRFD(EFL, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_FUNC_DIRFD], +[ +AC_LINK_IFELSE( + [ + AC_LANG_PROGRAM( + [[ +#ifdef HAVE_DIRENT_H +# include +#endif + ]], + [[ +int main(void) +{ + DIR *dirp; + return dirfd(dirp); +} + ]]) + ], + [_efl_have_fct="yes"], + [_efl_have_fct="no"]) + +AS_IF([test "x${_efl_have_fct}" = "xyes"], [$2], [$3]) +]) + +dnl _EFL_CHECK_FUNC_DLADDR_PRIV is for internal use +dnl _EFL_CHECK_FUNC_DLADDR_PRIV(EFL, LIB, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_FUNC_DLADDR_PRIV], +[ +m4_pushdef([UPEFL], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWNEFL], m4_translit([$1], [-A-Z], [_a-z]))dnl + +LIBS_save="${LIBS}" +LIBS="${LIBS} $2" +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#define _GNU_SOURCE +#include + ]], + [[ +int res = dladdr(0, 0); + ]])], + [ + m4_defn([UPEFL])[]_LIBS="${m4_defn([UPEFL])[]_LIBS} $2" + requirements_libs_[]m4_defn([DOWNEFL])="${requirements_libs_[]m4_defn([DOWNEFL])} $2" + _efl_have_fct="yes" + ], + [_efl_have_fct="no"]) + +LIBS="${LIBS_save}" + +AS_IF([test "x${_efl_have_fct}" = "xyes"], [$3], [$4]) + +m4_popdef([DOWNEFL]) +m4_popdef([UPEFL]) +]) + +dnl _EFL_CHECK_FUNC_DLADDR is for internal use +dnl _EFL_CHECK_FUNC_DLADDR(EFL, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_FUNC_DLADDR], +[ +m4_pushdef([UPEFL], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWNEFL], m4_translit([$1], [-A-Z], [_a-z]))dnl + +case "$host_os" in + mingw*) + _efl_have_fct="yes" + requirements_libs_[]m4_defn([DOWNEFL])="${requirements_libs_[]m4_defn([DOWNEFL])} -ldl" + m4_defn([UPEFL])[]_LIBS="${m4_defn([UPEFL])[]_LIBS} -ldl" + ;; + *) + _efl_have_fct="no" + +dnl Check is dladdr is in libc + _EFL_CHECK_FUNC_DLADDR_PRIV([$1], [], [_efl_have_fct="yes"], [_efl_have_fct="no"]) + +dnl Check is dlopen is in libdl + if test "x${_efl_have_fct}" = "xno" ; then + _EFL_CHECK_FUNC_DLADDR_PRIV([$1], [-ldl], [_efl_have_fct="yes"], [_efl_have_fct="no"]) + fi + ;; +esac + +AS_IF([test "x${_efl_have_fct}" = "xyes"], [$2], [$3]) + +m4_popdef([DOWNEFL]) +m4_popdef([UPEFL]) +]) + +dnl _EFL_CHECK_FUNC_DLOPEN_PRIV is for internal use +dnl _EFL_CHECK_FUNC_DLOPEN_PRIV(EFL, LIB, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_FUNC_DLOPEN_PRIV], +[ +m4_pushdef([UPEFL], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWNEFL], m4_translit([$1], [-A-Z], [_a-z]))dnl + +LIBS_save="${LIBS}" +LIBS="${LIBS} $2" +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include + ]], + [[ +void *h = dlopen(0, 0); + ]])], + [ + m4_defn([UPEFL])[]_LIBS="${m4_defn([UPEFL])[]_LIBS} $2" + requirements_libs_[]m4_defn([DOWNEFL])="${requirements_libs_[]m4_defn([DOWNEFL])} $2" + _efl_have_fct="yes" + ], + [_efl_have_fct="no"]) + +LIBS="${LIBS_save}" + +AS_IF([test "x${_efl_have_fct}" = "xyes"], [$3], [$4]) + +m4_popdef([DOWNEFL]) +m4_popdef([UPEFL]) +]) + +dnl _EFL_CHECK_FUNC_DLOPEN is for internal use +dnl _EFL_CHECK_FUNC_DLOPEN(EFL, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_FUNC_DLOPEN], +[ +m4_pushdef([UPEFL], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWNEFL], m4_translit([$1], [-A-Z], [_a-z]))dnl + +case "$host_os" in + mingw*) + _efl_have_fct="yes" + requirements_libs_[]m4_defn([DOWNEFL])="${requirements_libs_[]m4_defn([DOWNEFL])} -ldl" + m4_defn([UPEFL])[]_LIBS="${m4_defn([UPEFL])[]_LIBS} -ldl" + ;; + *) + _efl_have_fct="no" + +dnl Check is dlopen is in libc + _EFL_CHECK_FUNC_DLOPEN_PRIV([$1], [], [_efl_have_fct="yes"], [_efl_have_fct="no"]) + +dnl Check is dlopen is in libdl + if test "x${_efl_have_fct}" = "xno" ; then + _EFL_CHECK_FUNC_DLOPEN_PRIV([$1], [-ldl], [_efl_have_fct="yes"], [_efl_have_fct="no"]) + fi + ;; +esac + +AS_IF([test "x${_efl_have_fct}" = "xyes"], [$2], [$3]) + +m4_popdef([DOWNEFL]) +m4_popdef([UPEFL]) +]) + +dnl _EFL_CHECK_FUNC_FNMATCH_PRIV is for internal use +dnl _EFL_CHECK_FUNC_FNMATCH_PRIV(EFL, LIB, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_FUNC_FNMATCH_PRIV], +[ +m4_pushdef([UPEFL], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWNEFL], m4_translit([$1], [-A-Z], [_a-z]))dnl + +LIBS_save="${LIBS}" +LIBS="${LIBS} $2" +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[ +int g = fnmatch(NULL, NULL, 0); + ]])], + [ + m4_defn([UPEFL])[]_LIBS="${m4_defn([UPEFL])[]_LIBS} $2" + requirements_libs_[]m4_defn([DOWNEFL])="${requirements_libs_[]m4_defn([DOWNEFL])} $2" + _efl_have_fct="yes" + ], + [_efl_have_fct="no"]) + +LIBS="${LIBS_save}" + +AS_IF([test "x${_efl_have_fct}" = "xyes"], [$3], [$4]) + +m4_popdef([DOWNEFL]) +m4_popdef([UPEFL]) +]) + +dnl _EFL_CHECK_FUNC_FNMATCH is for internal use +dnl _EFL_CHECK_FUNC_FNMATCH(EFL, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_FUNC_FNMATCH], +[ +case "$host_os" in + mingw*) + _efl_have_fct="yes" + ;; + *) +dnl Check is fnmatch is in libc + _EFL_CHECK_FUNC_FNMATCH_PRIV([$1], [], [_efl_have_fct="yes"], [_efl_have_fct="no"]) + +dnl Check is fnmatch is in libfnmatch + if test "x${_efl_have_fct}" = "xno" ; then + _EFL_CHECK_FUNC_FNMATCH_PRIV([$1], [-lfnmatch], [_efl_have_fct="yes"], [_efl_have_fct="no"]) + fi + +dnl Check is fnmatch is in libiberty + if test "x${_efl_have_fct}" = "xno" ; then + _EFL_CHECK_FUNC_FNMATCH_PRIV([$1], [-liberty], [_efl_have_fct="yes"], [_efl_have_fct="no"]) + fi + ;; +esac + +AS_IF([test "x${_efl_have_fct}" = "xyes"], [$2], [$3]) +]) + +dnl _EFL_CHECK_FUNC_ICONV_PRIV is for internal use +dnl _EFL_CHECK_FUNC_ICONV_PRIV(EFL, LIB, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_FUNC_ICONV_PRIV], +[ +m4_pushdef([UPEFL], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWNEFL], m4_translit([$1], [-A-Z], [_a-z]))dnl + +LIBS_save="${LIBS}" +LIBS="${LIBS} $2" +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[ +iconv_t ic; +size_t count = iconv(ic, NULL, NULL, NULL, NULL); + ]])], + [ + m4_defn([UPEFL])[]_LIBS="${m4_defn([UPEFL])[]_LIBS} $2" + requirements_libs_[]m4_defn([DOWNEFL])="${requirements_libs_[]m4_defn([DOWNEFL])} $2" + _efl_have_fct="yes" + ], + [_efl_have_fct="no"]) + +LIBS="${LIBS_save}" + +AS_IF([test "x${_efl_have_fct}" = "xyes"], [$3], [$4]) + +m4_popdef([DOWNEFL]) +m4_popdef([UPEFL]) +]) + +dnl _EFL_CHECK_FUNC_ICONV is for internal use +dnl _EFL_CHECK_FUNC_ICONV(EFL, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_FUNC_ICONV], +[ +AC_ARG_WITH([iconv-link], + AC_HELP_STRING([--with-iconv-link=ICONV_LINK], [explicitly specify an iconv link option]), + [ + _efl_have_fct="yes" + iconv_libs=${withval} + ], + [_efl_have_fct="no"]) + +AC_MSG_CHECKING([for explicit iconv link options]) +if test "x${iconv_libs}" = "x" ; then + AC_MSG_RESULT([no explicit iconv link option]) +else + AC_MSG_RESULT([${iconv_libs}]) +fi + +dnl Check is iconv is in libc +if test "x${_efl_have_fct}" = "xno" ; then + _EFL_CHECK_FUNC_ICONV_PRIV([$1], [], [_efl_have_fct="yes"], [_efl_have_fct="no"]) +fi + +dnl Check is iconv is in libiconv +if test "x${_efl_have_fct}" = "xno" ; then + _EFL_CHECK_FUNC_ICONV_PRIV([$1], [-liconv], [_efl_have_fct="yes"], [_efl_have_fct="no"]) +fi + +dnl Check is iconv is in libiconv_plug +if test "x${_efl_have_fct}" = "xno" ; then + _EFL_CHECK_FUNC_ICONV_PRIV([$1], [-liconv_plug], [_efl_have_fct="yes"], [_efl_have_fct="no"]) +fi + +AS_IF([test "x${_efl_have_fct}" = "xyes"], [$2], [$3]) +]) + +dnl _EFL_CHECK_FUNC_SETXATTR is for internal use +dnl _EFL_CHECK_FUNC_SETXATTR(EFL, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_FUNC_SETXATTR], +[ +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include +#include + ]], + [[ +size_t tmp = listxattr("/", NULL, 0); +tmp = getxattr("/", "user.ethumb.md5", NULL, 0); +setxattr("/", "user.ethumb.md5", NULL, 0, 0); + ]])], + [_efl_have_fct="yes"], + [_efl_have_fct="no"]) + +AS_IF([test "x${_efl_have_fct}" = "xyes"], [$2], [$3]) +]) + +dnl _EFL_CHECK_FUNC_SHM_OPEN_PRIV is for internal use +dnl _EFL_CHECK_FUNC_SHM_OPEN_PRIV(EFL, LIB, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_FUNC_SHM_OPEN_PRIV], +[ +m4_pushdef([UPEFL], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWNEFL], m4_translit([$1], [-A-Z], [_a-z]))dnl + +LIBS_save="${LIBS}" +LIBS="${LIBS} $2" +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include /* For mode constants */ +#include /* For O_* constants */ + ]], + [[ +int fd; + +fd = shm_open("/dev/null", O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO); + ]])], + [ + m4_defn([UPEFL])[]_LIBS="$m4_defn([UPEFL])[]_LIBS $2" + requirements_libs_[]m4_defn([DOWNEFL])="${requirements_libs_[]m4_defn([DOWNEFL])} $2" + _efl_have_fct="yes" + ], + [_efl_have_fct="no"]) + +LIBS="${LIBS_save}" + +AS_IF([test "x${_efl_have_fct}" = "xyes"], [$3], [$4]) + +m4_popdef([DOWNEFL]) +m4_popdef([UPEFL]) +]) + +dnl _EFL_CHECK_FUNC_SHM_OPEN is for internal use +dnl _EFL_CHECK_FUNC_SHM_OPEN(EFL, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_FUNC_SHM_OPEN], +[ +_efl_have_fct="no" + +dnl Check is shm_open is in libc +_EFL_CHECK_FUNC_SHM_OPEN_PRIV([$1], [], + [_efl_have_fct="yes"], + [_efl_have_fct="no"]) + +dnl Check is shm_open is in librt +if test "x${_efl_have_fct}" = "xno" ; then + _EFL_CHECK_FUNC_SHM_OPEN_PRIV([$1], [-lrt], + [_efl_have_fct="yes"], + [_efl_have_fct="no"]) +fi + +AS_IF([test "x${_efl_have_fct}" = "xyes"], [$2], [$3]) +]) + +dnl Macro that checks function availability +dnl +dnl EFL_CHECK_FUNC(EFL, FUNCTION) +dnl AC_DEFINE : EFL_HAVE_FUNCTION (FUNCTION being replaced by its value) +dnl result in efl_func_function (function being replaced by its value) + +AC_DEFUN([EFL_CHECK_FUNC], +[ +m4_pushdef([UP], m4_translit([$2], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWN], m4_translit([$2], [-A-Z], [_a-z]))dnl + +m4_default([_EFL_CHECK_FUNC_]m4_defn([UP]))($1, [have_fct="yes"], [have_fct="no"]) + +if test "x$2" = "xsetxattr" ; then + AC_MSG_CHECKING([for extended attributes]) +else + AC_MSG_CHECKING([for ]m4_defn([DOWN])) +fi + +AC_MSG_RESULT([${have_fct}]) + +if test "x${have_fct}" = "xyes" ; then + if test "x$2" = "xsetxattr" ; then + AC_DEFINE([HAVE_XATTR], [1], [Define to 1 if you have the `listxattr', `setxattr' and `getxattr' functions.]) + else + AC_DEFINE([HAVE_]m4_defn([UP]), [1], [Define to 1 if you have the `]m4_defn([DOWN])[' function.]) + fi +fi + +efl_func_[]m4_defn([DOWN])="${have_fct}" + +m4_popdef([DOWN]) +m4_popdef([UP]) +]) + +dnl Macro that iterates over a sequence of space separated functions +dnl and that calls EFL_CHECK_FUNC() for each of these functions +dnl +dnl EFL_CHECK_FUNCS(EFL, FUNCTIONS) + +AC_DEFUN([EFL_CHECK_FUNCS], +[ +m4_foreach_w([fct], [$2], [EFL_CHECK_FUNC($1, m4_defn([fct]))]) +]) diff --git a/m4/efl_check_libs.m4 b/m4/efl_check_libs.m4 new file mode 100644 index 0000000..b1c3789 --- /dev/null +++ b/m4/efl_check_libs.m4 @@ -0,0 +1,119 @@ +dnl Copyright (C) 2012 Vincent Torri +dnl This code is public domain and can be freely used or copied. + +dnl Macro that check dependencies libraries for the EFL: + +dnl libjpeg +dnl zlib + +dnl _EFL_CHECK_LIB_LIBJPEG is for internal use +dnl _EFL_CHECK_LIB_LIBJPEG(EFL, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_LIB_LIBJPEG], +[ +m4_pushdef([UPEFL], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWNEFL], m4_translit([$1], [-A-Z], [_a-z]))dnl + +AC_CHECK_HEADER([jpeglib.h], + [have_dep="yes"], + [ + AC_MSG_ERROR(["Cannot find jpeglib.h. Make sure your CFLAGS environment variable contains include lines for the location of this file"]) + have_dep="no" + ]) + +if test "x${have_dep}" = "xyes" ; then + AC_CHECK_LIB([jpeg], [jpeg_std_error], + [ + have_dep="yes" + requirements_libs_[]m4_defn([DOWNEFL])="${requirements_libs_[]m4_defn([DOWNEFL])} -ljpeg" + ], + [ + AC_MSG_ERROR("Cannot find libjpeg library. Make sure your LDFLAGS environment variable contains include lines for the location of this file") + have_dep="no" + ]) +fi + +AS_IF([test "x${have_dep}" = "xyes"], [$2], [$3]) + +m4_popdef([DOWNEFL]) +m4_popdef([UPEFL]) +]) + +dnl _EFL_CHECK_LIB_ZLIB is for internal use +dnl _EFL_CHECK_LIB_ZLIB(EFL, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) + +AC_DEFUN([_EFL_CHECK_LIB_ZLIB], +[ +m4_pushdef([UPEFL], m4_translit([$1], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWNEFL], m4_translit([$1], [-A-Z], [_a-z]))dnl + +PKG_CHECK_EXISTS([zlib], + [ + _efl_have_lib="yes" + requirements_pc_[]m4_defn([DOWNEFL])="${requirements_pc_[]m4_defn([DOWNEFL])} zlib" + ], + [ + _efl_have_lib="no" + ]) + +if test "x${_efl_have_lib}" = "xno" ; then + AC_CHECK_HEADER([zlib.h], + [_efl_have_lib="yes"], + [ + AC_MSG_ERROR(["Cannot find zlib.h. Make sure your CFLAGS environment variable contains include lines for the location of this file"]) + _efl_have_lib="no" + ]) + + if test "x${_efl_have_lib}" = "xyes" ; then + AC_CHECK_LIB([z], [zlibVersion], + [ + _efl_have_lib="yes" + requirements_libs_[]m4_defn([DOWNEFL])="${requirements_libs_[]m4_defn([DOWNEFL])} -lz" + ], + [ + AC_MSG_ERROR(["Cannot find libjpeg library. Make sure your LDFLAGS environment variable contains include lines for the location of this file"]) + _efl_have_lib="no" + ]) + fi +fi + +AS_IF([test "x${_efl_have_lib}" = "xyes"], [$2], [$3]) + +m4_popdef([DOWNEFL]) +m4_popdef([UPEFL]) +]) + +dnl Macro that checks for a library +dnl +dnl EFL_CHECK_LIB(EFL, LIBRARY) +dnl AC_DEFINE : EFL_HAVE_LIBRARY (LIBRARY being replaced by its value) + +AC_DEFUN([EFL_CHECK_LIB], +[ +m4_pushdef([UP], m4_translit([$2], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWN], m4_translit([$2], [-A-Z], [_a-z]))dnl + +m4_default([_EFL_CHECK_LIB_]m4_defn([UP]))($1, [have_lib="yes"], [have_lib="no"]) + +AC_MSG_CHECKING([for ]m4_defn([DOWN])) +AC_MSG_RESULT([${have_lib}]) + +if test "x${have_lib}" = "xyes" ; then + AC_DEFINE([HAVE_]m4_defn([UP]), [1], [Define to 1 if the `]m4_defn([DOWN])[' library is installed.]) +fi + +efl_lib_[]m4_defn([DOWN])="${have_lib}" + +m4_popdef([DOWN]) +m4_popdef([UP]) +]) + +dnl Macro that iterates over a sequence of white separated libraries +dnl and that calls EFL_CHECK_LIB() for each of these libraries +dnl +dnl EFL_CHECK_LIBS(EFL, LIBRARIES) + +AC_DEFUN([EFL_CHECK_LIBS], +[ +m4_foreach_w([lib], [$2], [EFL_CHECK_LIB($1, m4_defn([lib]))]) +]) diff --git a/m4/efl_compiler_flag.m4 b/m4/efl_compiler_flag.m4 new file mode 100644 index 0000000..618c6a6 --- /dev/null +++ b/m4/efl_compiler_flag.m4 @@ -0,0 +1,57 @@ +dnl Copyright (C) 2010 Vincent Torri +dnl and Albin Tonnerre +dnl That code is public domain and can be freely used or copied. + +dnl Macro that checks if a compiler flag is supported by the compiler. + +dnl Usage: EFL_COMPILER_FLAG(flag) +dnl flag is added to CFLAGS if supported. + +AC_DEFUN([EFL_COMPILER_FLAG], +[ + +CFLAGS_save="${CFLAGS}" +CFLAGS="${CFLAGS} $1" + +AC_LANG_PUSH([C]) +AC_MSG_CHECKING([whether the compiler supports $1]) + +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[]])], + [have_flag="yes"], + [have_flag="no"]) +AC_MSG_RESULT([${have_flag}]) + +if test "x${have_flag}" = "xno" ; then + CFLAGS="${CFLAGS_save}" +fi +AC_LANG_POP([C]) + +]) + +dnl Macro that checks if a linker flag is supported by the compiler. + +dnl Usage: EFL_LINKER_FLAG(flag) +dnl flag is added to CFLAGS if supported (will be passed to ld anyway). + +AC_DEFUN([EFL_LINKER_FLAG], +[ + +CFLAGS_save="${CFLAGS}" +CFLAGS="${CFLAGS} $1" + +AC_LANG_PUSH([C]) +AC_MSG_CHECKING([whether the compiler supports $1]) + +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[]])], + [have_flag="yes"], + [have_flag="no"]) +AC_MSG_RESULT([${have_flag}]) + +if test "x${have_flag}" = "xno" ; then + CFLAGS="${CFLAGS_save}" +fi +AC_LANG_POP([C]) + +]) diff --git a/m4/efl_doxygen.m4 b/m4/efl_doxygen.m4 new file mode 100644 index 0000000..7324af3 --- /dev/null +++ b/m4/efl_doxygen.m4 @@ -0,0 +1,94 @@ +dnl Copyright (C) 2008 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if doxygen is available or not. + +dnl EFL_CHECK_DOXYGEN([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Test for the doxygen program +dnl Defines efl_doxygen +dnl Defines the automake conditionnal EFL_BUILD_DOC +dnl +AC_DEFUN([EFL_CHECK_DOXYGEN], +[ + +dnl +dnl Disable the build of the documentation +dnl +AC_ARG_ENABLE([doc], + [AC_HELP_STRING( + [--disable-doc], + [Disable documentation build @<:@default=enabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + efl_enable_doc="yes" + else + efl_enable_doc="no" + fi + ], + [efl_enable_doc="yes"]) + +AC_MSG_CHECKING([whether to build documentation]) +AC_MSG_RESULT([${efl_enable_doc}]) + +if test "x${efl_enable_doc}" = "xyes" ; then + +dnl Specify the file name, without path + + efl_doxygen="doxygen" + + AC_ARG_WITH([doxygen], + [AC_HELP_STRING( + [--with-doxygen=FILE], + [doxygen program to use @<:@default=doxygen@:>@])], + +dnl Check the given doxygen program. + + [efl_doxygen=${withval} + AC_CHECK_PROG([efl_have_doxygen], + [${efl_doxygen}], + [yes], + [no]) + if test "x${efl_have_doxygen}" = "xno" ; then + echo "WARNING:" + echo "The doxygen program you specified:" + echo "${efl_doxygen}" + echo "was not found. Please check the path and make sure " + echo "the program exists and is executable." + AC_MSG_WARN([no doxygen detected. Documentation will not be built]) + fi + ], + [AC_CHECK_PROG([efl_have_doxygen], + [${efl_doxygen}], + [yes], + [no]) + if test "x${efl_have_doxygen}" = "xno" ; then + echo "WARNING:" + echo "The doxygen program was not found in your execute path." + echo "You may have doxygen installed somewhere not covered by your path." + echo "" + echo "If this is the case make sure you have the packages installed, AND" + echo "that the doxygen program is in your execute path (see your" + echo "shell manual page on setting the \$PATH environment variable), OR" + echo "alternatively, specify the program to use with --with-doxygen." + AC_MSG_WARN([no doxygen detected. Documentation will not be built]) + fi + ]) +else + efl_have_doxygen="no" +fi + +dnl +dnl Substitution +dnl +AC_SUBST([efl_doxygen]) + +if ! test "x${efl_have_doxygen}" = "xyes" ; then + efl_enable_doc="no" +fi + +AM_CONDITIONAL(EFL_BUILD_DOC, test "x${efl_have_doxygen}" = "xyes") + +AS_IF([test "x$efl_have_doxygen" = "xyes"], [$1], [$2]) +]) + +dnl End of efl_doxygen.m4 diff --git a/m4/efl_path_max.m4 b/m4/efl_path_max.m4 new file mode 100644 index 0000000..f57bfd2 --- /dev/null +++ b/m4/efl_path_max.m4 @@ -0,0 +1,36 @@ +dnl Check for PATH_MAX in limits.h, and define a default value if not found +dnl This is a workaround for systems not providing PATH_MAX, like GNU/Hurd + +dnl EFL_CHECK_PATH_MAX([DEFAULT_VALUE_IF_NOT_FOUND]) +dnl +dnl If PATH_MAX is not defined in , defines it +dnl to DEFAULT_VALUE_IF_NOT_FOUND if it exists, or fallback +dnl to using 4096 + +AC_DEFUN([EFL_CHECK_PATH_MAX], +[ + +default_max=m4_default([$1], "4096") +AC_LANG_PUSH([C]) + +AC_MSG_CHECKING([for PATH_MAX in limits.h]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include + ]], + [[ +int i = PATH_MAX; + ]])], + [AC_MSG_RESULT([yes])], + [ + AC_DEFINE_UNQUOTED([PATH_MAX], + [${default_max}], + [default value since PATH_MAX is not defined]) + AC_MSG_RESULT([no: using ${default_max}]) + ]) + +AC_LANG_POP([C]) + +]) +dnl end of efl_path_max.m4 diff --git a/m4/efl_tests.m4 b/m4/efl_tests.m4 new file mode 100644 index 0000000..d8554e1 --- /dev/null +++ b/m4/efl_tests.m4 @@ -0,0 +1,65 @@ +dnl Copyright (C) 2008-2012 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if tests programs are wanted and if yes, if +dnl the Check library is available. +dnl the lcov program is available. + +dnl Usage: EFL_CHECK_TESTS(EFL[, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Define the automake conditionnal EFL_ENABLE_TESTS + +AC_DEFUN([EFL_CHECK_TESTS], +[ +m4_pushdef([UPEFL], m4_translit([$1], [-a-z], [_A-Z]))dnl + +dnl configure option + +AC_ARG_ENABLE([tests], + [AC_HELP_STRING([--enable-tests], [enable tests @<:@default=disabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + _efl_enable_tests="yes" + else + _efl_enable_tests="no" + fi + ], + [_efl_enable_tests="no"]) + +AC_MSG_CHECKING([whether tests are built]) +AC_MSG_RESULT([${_efl_enable_tests}]) + +AC_REQUIRE([PKG_PROG_PKG_CONFIG]) + +if test "x${_efl_enable_tests}" = "xyes" ; then + PKG_CHECK_MODULES([CHECK], + [check >= 0.9.5], + [dummy="yes"], + [_efl_enable_tests="no"]) +fi + +efl_enable_coverage="no" +if test "x${_efl_enable_tests}" = "xyes" ; then + AC_CHECK_PROG(have_lcov, [lcov], [yes], [no]) + if test "x$have_lcov" = "xyes" ; then + m4_defn([UPEFL])[]_CFLAGS="${m4_defn([UPEFL])[]_CFLAGS} -fprofile-arcs -ftest-coverage" + m4_defn([UPEFL])[]_LIBS="${m4_defn([UPEFL])[]_LIBS} -lgcov" +# remove any optimisation flag and force debug symbols + if test "x${prefer_assert}" = "xno"; then + m4_defn([UPEFL])[]_CFLAGS="${m4_defn([UPEFL])[]_CFLAGS} -DNDEBUG" + else + m4_defn([UPEFL])[]_CFLAGS="${m4_defn([UPEFL])[]_CFLAGS} -g -O0 -DDEBUG" + fi + efl_enable_coverage="yes" + else + AC_MSG_WARN([lcov is not found, disable profiling instrumentation]) + fi +fi + +AM_CONDITIONAL(EFL_ENABLE_TESTS, test "x${_efl_enable_tests}" = "xyes") + +AS_IF([test "x$_efl_enable_tests" = "xyes"], [$2], [$3]) + +m4_popdef([UPEFL]) +]) + +dnl End of efl_tests.m4 diff --git a/packaging/eet.spec b/packaging/eet.spec new file mode 100644 index 0000000..1e75b4c --- /dev/null +++ b/packaging/eet.spec @@ -0,0 +1,102 @@ +Name: eet +Summary: Library for speedy data storage, retrieval, and compression +Version: 1.7.1+svn.77495+build01r01 +Release: 1 +Group: System/Libraries +License: BSD +URL: http://www.enlightenment.org/ +Source0: %{name}-%{version}.tar.gz +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig +BuildRequires: eina-devel +BuildRequires: gnutls-devel +BuildRequires: zlib-devel +BuildRequires: libjpeg-turbo-devel + + +%description +Enlightenment DR17 file chunk reading/writing library development files Eet is a tiny library designed to write an arbitary set of chunks of data to a + file and optionally compress each chunk (very much like a zip file) and allow + fast random-access reading of the file later on. It does not do zip as zip + itself has more complexity than we need, and it was much simpler to implement + this once here. + . + This package contains headers and static libraries for development with libeet. + + +%package devel +Summary: Library for speedy data storage, retrieval, and compression (devel) +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + + +%description devel +Enlightenment DR17 file chunk reading/writing library (devel) + + +%package tools +Summary: Library for speedy data storage, retrieval, and compression. (tools) +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} +Provides: %{name}-bin +Obsoletes: %{name}-bin + + +%description tools +Enlightenment DR17 file chunk reading/writing library (tools) + + +%prep +%setup -q + + +%build +export CFLAGS+=" -fvisibility=hidden -fPIC" +export LDFLAGS+=" -fvisibility=hidden -Wl,--hash-style=both -Wl,--as-needed" + +%autogen --disable-static +%configure --disable-static \ + --disable-openssl --disable-cypher --disable-signature --disable-gnutls + +make %{?jobs:-j%jobs} + + +%install +rm -rf %{buildroot} +%make_install +mkdir -p %{buildroot}/usr/share/license +cp %{_builddir}/%{buildsubdir}/COPYING %{buildroot}/usr/share/license/%{name} + + +%post -p /sbin/ldconfig + + +%postun -p /sbin/ldconfig + + +%files +%defattr(-,root,root,-) +%{_libdir}/libeet.so.* +%manifest %{name}.manifest +/usr/share/license/%{name} +%manifest %{name}.manifest + + +%files devel +%defattr(-,root,root,-) +%{_includedir}/* +%{_libdir}/*.so +%{_libdir}/pkgconfig/eet.pc + + +%files tools +%defattr(-,root,root,-) +%{_bindir}/* +%{_datadir}/eet/examples/eet-basic.c +%{_datadir}/eet/examples/eet-data-cipher_decipher.c +%{_datadir}/eet/examples/eet-data-file_descriptor_01.c +%{_datadir}/eet/examples/eet-data-file_descriptor_02.c +%{_datadir}/eet/examples/eet-data-nested.c +%{_datadir}/eet/examples/eet-data-simple.c +%{_datadir}/eet/examples/eet-file.c + diff --git a/src/Makefile.am b/src/Makefile.am index a6fc38f..d98d3b6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,3 @@ MAINTAINERCLEANFILES = Makefile.in -SUBDIRS = lib bin tests +SUBDIRS = lib bin tests examples diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 024932f..3b83f76 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -7,12 +7,12 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ -DPACKAGE_BIN_DIR=\"$(bindir)\" \ -DPACKAGE_LIB_DIR=\"$(libdir)\" \ --DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +@EET_CFLAGS@ -bin_PROGRAMS = eet +bin_PROGRAMS = @EET_PRG@ +EXTRA_PROGRAMS = eet eet_SOURCES = eet_main.c -eet_CFLAGS = @WIN32_CFLAGS@ -eet_LDADD = $(top_builddir)/src/lib/libeet.la +eet_LDADD = $(top_builddir)/src/lib/libeet.la @EET_LIBS@ eet_LDFLAGS = @lt_enable_auto_import@ -eet_DEPENDENCIES = $(top_builddir)/src/lib/libeet.la diff --git a/src/bin/eet_main.c b/src/bin/eet_main.c index d352a0f..8a93d11 100644 --- a/src/bin/eet_main.c +++ b/src/bin/eet_main.c @@ -1,9 +1,48 @@ +#ifdef HAVE_CONFIG_H +# include +#endif /* ifdef HAVE_CONFIG_H */ + #include #include -#include #include + +#ifdef HAVE_UNISTD_H +# include +#endif /* ifdef HAVE_UNISTD_H */ + +#ifdef HAVE_EVIL +# include +#endif /* ifdef HAVE_EVIL */ + #include +static int _eet_main_log_dom = -1; + +#ifdef EET_DEFAULT_LOG_COLOR +#undef EET_DEFAULT_LOG_COLOR +#endif /* ifdef EET_DEFAULT_LOG_COLOR */ +#define EET_DEFAULT_LOG_COLOR EINA_COLOR_CYAN +#ifdef ERR +#undef ERR +#endif /* ifdef ERR */ +#define ERR(...) EINA_LOG_DOM_ERR(_eet_main_log_dom, __VA_ARGS__) +#ifdef DBG +#undef DBG +#endif /* ifdef DBG */ +#define DBG(...) EINA_LOG_DOM_DBG(_eet_main_log_dom, __VA_ARGS__) +#ifdef INF +#undef INF +#endif /* ifdef INF */ +#define INF(...) EINA_LOG_DOM_INFO(_eet_main_log_dom, __VA_ARGS__) +#ifdef WRN +#undef WRN +#endif /* ifdef WRN */ +#define WRN(...) EINA_LOG_DOM_WARN(_eet_main_log_dom, __VA_ARGS__) +#ifdef CRIT +#undef CRIT +#endif /* ifdef CRIT */ +#define CRIT(...) EINA_LOG_DOM_CRIT(_eet_main_log_dom, __VA_ARGS__) + static void do_eet_list(const char *file) { @@ -14,90 +53,173 @@ do_eet_list(const char *file) ef = eet_open(file, EET_FILE_MODE_READ); if (!ef) { - printf("cannot open for reading: %s\n", file); - exit(-1); + ERR("cannot open for reading: %s", file); + exit(-1); } + list = eet_list(ef, "*", &num); if (list) { - for (i = 0; i < num; i++) - printf("%s\n",list[i]); - free(list); + for (i = 0; i < num; i++) + printf("%s\n", list[i]); + free(list); + } + + eet_close(ef); +} /* do_eet_list */ + +static void +do_eet_stats(const char *file) +{ + int i, num; + int count[2] = { 0, 0 }; + int size[2] = { 0, 0 }; + char **list; + Eet_File *ef; + Eet_Dictionary *ed; + + ef = eet_open(file, EET_FILE_MODE_READ); + if (!ef) + { + ERR("cannot open for reading: %s", file); + exit(-1); + } + + printf("*** sections stats ***\n"); + list = eet_list(ef, "*", &num); + if (list) + { + for (i = 0; i < num; i++) + { + const void *ro = NULL; + void *rw = NULL; + int tsize; + + ro = eet_read_direct(ef, list[i], &tsize); + if (!ro) rw = eet_read(ef, list[i], &tsize); + printf(rw ? "%s of size %i is compressed.\n" : "%s of size %i is not compressed.\n", list[i], tsize); + count[rw ? 0 : 1]++; + size[rw ? 0 : 1] += tsize; + free(rw); + } + free(list); + } + + printf("*** dictionary ***\n"); + ed = eet_dictionary_get(ef); + if (ed) + { + printf("%i strings inside the dictionary.\n", eet_dictionary_count(ed)); + } + else + { + printf("no dictionary in this file.\n"); } + printf("*** global ***\n"); + printf("%i sections\n", num); + printf("- %i of them are compressed (%02.2f%%) expanding in %i bytes.\n", + count[0], (float) count[0] * 100 / (float) num, size[0]); + printf("- %i of them are directly mappable in memory (%02.2f%%) representing %i bytes.\n", + count[1], (float) count[1] * 100 / (float) num, size[1]); + eet_close(ef); } static void -do_eet_extract(const char *file, const char *key, const char *out) +do_eet_extract(const char *file, + const char *key, + const char *out, + const char *crypto_key) { Eet_File *ef; void *data; int size = 0; - FILE *f; + FILE *f = stdout; ef = eet_open(file, EET_FILE_MODE_READ); if (!ef) { - printf("cannot open for reading: %s\n", file); - exit(-1); + ERR("cannot open for reading: %s", file); + exit(-1); } - data = eet_read(ef, key, &size); + + data = eet_read_cipher(ef, key, &size, crypto_key); if (!data) { - printf("cannot read key %s\n", key); - exit(-1); + ERR("cannot read key %s", key); + exit(-1); } - f = fopen(out, "w"); - if (!f) + + if (out) { - printf("cannot open %s\n", out); - exit(-1); + f = fopen(out, "wb"); + if (!f) + { + ERR("cannot open %s", out); + exit(-1); + } } + if (fwrite(data, size, 1, f) != 1) { - printf("cannot write to %s\n", out); - exit(-1); + ERR("cannot write to %s", out ? out : "standard output"); + exit(-1); } - fclose(f); + + if (out) fclose(f); free(data); eet_close(ef); -} +} /* do_eet_extract */ static void -do_eet_decode_dump(void *data, const char *str) +do_eet_decode_dump(void *data, + const char *str) { fputs(str, (FILE *)data); -} +} /* do_eet_decode_dump */ static void -do_eet_decode(const char *file, const char *key, const char *out) +do_eet_decode(const char *file, + const char *key, + const char *out, + const char *crypto_key) { Eet_File *ef; - FILE *f; + FILE *f = stdout; ef = eet_open(file, EET_FILE_MODE_READ); if (!ef) { - printf("cannot open for reading: %s\n", file); - exit(-1); + ERR("cannot open for reading: %s", file); + exit(-1); } - f = fopen(out, "w"); - if (!f) + + if (out) { - printf("cannot open %s\n", out); - exit(-1); + f = fopen(out, "wb"); + if (!f) + { + ERR("cannot open %s", out); + exit(-1); + } } - if (!eet_data_dump(ef, key, do_eet_decode_dump, f)) + + if (!eet_data_dump_cipher(ef, key, crypto_key, do_eet_decode_dump, f)) { - printf("cannot write to %s\n", out); - exit(-1); + ERR("cannot write to %s", out ? out : "standard output"); + exit(-1); } - fclose(f); + + if (out) fclose(f); eet_close(ef); -} +} /* do_eet_decode */ static void -do_eet_insert(const char *file, const char *key, const char *out, int compress) +do_eet_insert(const char *file, + const char *key, + const char *out, + int compress, + const char *crypto_key) { Eet_File *ef; void *data; @@ -107,39 +229,48 @@ do_eet_insert(const char *file, const char *key, const char *out, int compress) ef = eet_open(file, EET_FILE_MODE_READ_WRITE); if (!ef) ef = eet_open(file, EET_FILE_MODE_WRITE); + if (!ef) { - printf("cannot open for read+write: %s\n", file); - exit(-1); + ERR("cannot open for read+write: %s", file); + exit(-1); } - f = fopen(out, "r"); + + f = fopen(out, "rb"); if (!f) { - printf("cannot open %s\n", out); - exit(-1); + ERR("cannot open %s", out); + exit(-1); } + fseek(f, 0, SEEK_END); size = ftell(f); rewind(f); data = malloc(size); if (!data) { - printf("cannot allocate %i bytes\n", size); - exit(-1); + ERR("cannot allocate %i bytes", size); + exit(-1); } + if (fread(data, size, 1, f) != 1) { - printf("cannot read file %s\n", out); - exit(-1); + ERR("cannot read file %s", out); + exit(-1); } + fclose(f); - eet_write(ef, key, data, size, compress); + eet_write_cipher(ef, key, data, size, compress, crypto_key); free(data); eet_close(ef); -} +} /* do_eet_insert */ static void -do_eet_encode(const char *file, const char *key, const char *out, int compress) +do_eet_encode(const char *file, + const char *key, + const char *out, + int compress, + const char *crypto_key) { Eet_File *ef; char *text; @@ -150,102 +281,227 @@ do_eet_encode(const char *file, const char *key, const char *out, int compress) ef = eet_open(file, EET_FILE_MODE_READ_WRITE); if (!ef) ef = eet_open(file, EET_FILE_MODE_WRITE); + if (!ef) { - printf("cannot open for read+write: %s\n", file); - exit(-1); + ERR("cannot open for read+write: %s", file); + exit(-1); } - f = fopen(out, "r"); + + f = fopen(out, "rb"); if (!f) { - printf("cannot open %s\n", out); - exit(-1); + ERR("cannot open %s", out); + exit(-1); } + fseek(f, 0, SEEK_END); textlen = ftell(f); rewind(f); text = malloc(textlen); if (!text) { - printf("cannot allocate %i bytes\n", size); - exit(-1); + ERR("cannot allocate %i bytes", size); + exit(-1); } + if (fread(text, textlen, 1, f) != 1) { - printf("cannot read file %s\n", out); - exit(-1); + ERR("cannot read file %s", out); + exit(-1); } + fclose(f); - if (!eet_data_undump(ef, key, text, textlen, compress)) + if (!eet_data_undump_cipher(ef, key, crypto_key, text, textlen, compress)) { - printf("cannot parse %s\n", out); - exit(-1); + ERR("cannot parse %s", out); + exit(-1); } + free(text); eet_close(ef); -} +} /* do_eet_encode */ static void -do_eet_remove(const char *file, const char *key) +do_eet_remove(const char *file, + const char *key) { Eet_File *ef; ef = eet_open(file, EET_FILE_MODE_READ_WRITE); if (!ef) { - printf("cannot open for read+write: %s\n", file); - exit(-1); + ERR("cannot open for read+write: %s", file); + exit(-1); } + eet_delete(ef, key); eet_close(ef); -} +} /* do_eet_remove */ -int -main(int argc, char **argv) +static void +do_eet_check(const char *file) { - eet_init(); - if (argc < 2) + Eet_File *ef; + const void *der; + int der_length; + int sign_length; + + ef = eet_open(file, EET_FILE_MODE_READ); + if (!ef) { - help: - printf("Usage:\n" - " eet -l FILE.EET list all keys in FILE.EET\n" - " eet -x FILE.EET KEY OUT-FILE extract data stored in KEY in FILE.EET and write to OUT-FILE\n" - " eet -d FILE.EET KEY OUT-FILE extract and decode data stored in KEY in FILE.EET and write to OUT-FILE\n" - " eet -i FILE.EET KEY IN-FILE COMPRESS insert data to KEY in FILE.EET from IN-FILE and if COMPRESS is 1, compress it\n" - " eet -e FILE.EET KEY IN-FILE COMPRESS insert and encode to KEY in FILE.EET from IN-FILE and if COMPRESS is 1, compress it\n" - " eet -r FILE.EET KEY remove KEY in FILE.EET\n" - ); - eet_shutdown(); - return 0; + ERR("checking signature of `%s` failed", file); + exit(-1); } - if ((!strncmp(argv[1], "-h", 2))) + + der = eet_identity_x509(ef, &der_length); + + fprintf(stdout, "Certificate length %i.\n", der_length); + eet_identity_certificate_print(der, der_length, stdout); + + eet_identity_signature(ef, &sign_length); + fprintf(stdout, "Signature length %i.\n", sign_length); + + eet_close(ef); +} /* do_eet_check */ + +static void +do_eet_sign(const char *file, + const char *private_key, + const char *public_key) +{ + Eet_File *ef; + Eet_Key *key; + + ef = eet_open(file, EET_FILE_MODE_READ_WRITE); + if (!ef) { - goto help; + ERR("cannot open for read+write: %s.", file); + exit(-1); } - else if ((!strcmp(argv[1], "-l")) && (argc > 2)) + + key = eet_identity_open(public_key, private_key, NULL); + if (!key) + { + ERR("cannot open key '%s:%s'.", public_key, private_key); + exit(-1); + } + + fprintf(stdout, "Using the following key to sign `%s`.\n", file); + eet_identity_print(key, stdout); + + eet_identity_set(ef, key); + + eet_close(ef); +} /* do_eet_sign */ + +int +main(int argc, + char **argv) +{ + if (!eet_init()) + return -1; + + _eet_main_log_dom = eina_log_domain_register("eet_main", EINA_COLOR_CYAN); + if(_eet_main_log_dom < -1) { - do_eet_list(argv[2]); + EINA_LOG_ERR("Impossible to create a log domain for eet_main."); + eet_shutdown(); + return -1; } - else if ((!strcmp(argv[1], "-x")) && (argc > 4)) + + if (argc < 2) { - do_eet_extract(argv[2], argv[3], argv[4]); +help: + printf( + "Usage:\n" + " eet -l FILE.EET list all keys in FILE.EET\n" + " eet -x FILE.EET KEY [OUT-FILE] [CRYPTO_KEY] extract data stored in KEY in FILE.EET and write to OUT-FILE or standard output\n" + " eet -d FILE.EET KEY [OUT-FILE] [CRYPTO_KEY] extract and decode data stored in KEY in FILE.EET and write to OUT-FILE or standard output\n" + " eet -i FILE.EET KEY IN-FILE COMPRESS [CRYPTO_KEY] insert data to KEY in FILE.EET from IN-FILE and if COMPRESS is 1, compress it\n" + " eet -e FILE.EET KEY IN-FILE COMPRESS [CRYPTO_KEY] insert and encode to KEY in FILE.EET from IN-FILE and if COMPRESS is 1, compress it\n" + " eet -r FILE.EET KEY remove KEY in FILE.EET\n" + " eet -c FILE.EET report and check the signature information of an eet file\n" + " eet -s FILE.EET PRIVATE_KEY PUBLIC_KEY sign FILE.EET with PRIVATE_KEY and attach PUBLIC_KEY as it's certificate\n" + " eet -t FILE.EET give some statistic about a file\n" + ); + eet_shutdown(); + return -1; } - else if ((!strcmp(argv[1], "-d")) && (argc > 4)) + + if ((!strncmp(argv[1], "-h", 2))) + goto help; + else if ((!strcmp(argv[1], "-l")) && (argc > 2)) + do_eet_list(argv[2]); + else if ((!strcmp(argv[1], "-x")) && (argc > 3)) { - do_eet_decode(argv[2], argv[3], argv[4]); + switch (argc) + { + case 4: + { + do_eet_extract(argv[2], argv[3], NULL, NULL); + break; + } + case 5: + { + do_eet_extract(argv[2], argv[3], argv[4], NULL); + break; + } + default: + { + do_eet_extract(argv[2], argv[3], argv[4], argv[5]); + break; + } + } + } + else if ((!strcmp(argv[1], "-d")) && (argc > 3)) + { + switch (argc) + { + case 4: + { + do_eet_decode(argv[2], argv[3], NULL, NULL); + break; + } + case 5: + { + do_eet_decode(argv[2], argv[3], argv[4], NULL); + break; + } + default: + { + do_eet_decode(argv[2], argv[3], argv[4], argv[5]); + break; + } + } } else if ((!strcmp(argv[1], "-i")) && (argc > 5)) { - do_eet_insert(argv[2], argv[3], argv[4], atoi(argv[5])); + if (argc > 6) + do_eet_insert(argv[2], argv[3], argv[4], atoi(argv[5]), argv[6]); + else + do_eet_insert(argv[2], argv[3], argv[4], atoi(argv[5]), NULL); } else if ((!strcmp(argv[1], "-e")) && (argc > 5)) { - do_eet_encode(argv[2], argv[3], argv[4], atoi(argv[5])); + if (argc > 6) + do_eet_encode(argv[2], argv[3], argv[4], atoi(argv[5]), argv[6]); + else + do_eet_encode(argv[2], argv[3], argv[4], atoi(argv[5]), NULL); } else if ((!strcmp(argv[1], "-r")) && (argc > 3)) - { - do_eet_remove(argv[2], argv[3]); - } + do_eet_remove(argv[2], argv[3]); + else if ((!strcmp(argv[1], "-c")) && (argc > 2)) + do_eet_check(argv[2]); + else if ((!strcmp(argv[1], "-s")) && (argc > 4)) + do_eet_sign(argv[2], argv[3], argv[4]); + else if ((!strcmp(argv[1], "-t")) && (argc > 2)) + do_eet_stats(argv[2]); + else + goto help; + + eina_log_domain_unregister(_eet_main_log_dom); eet_shutdown(); return 0; -} +} /* main */ + diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am new file mode 100644 index 0000000..4ad6f28 --- /dev/null +++ b/src/examples/Makefile.am @@ -0,0 +1,50 @@ +MAINTAINERCLEANFILES = Makefile.in + +examplesdir = $(datadir)/$(PACKAGE)/examples + +if BUILD_EXAMPLES +AM_CPPFLAGS = \ +-I. \ +-I$(top_srcdir)/src/lib \ +@EET_CFLAGS@ + +examples_PROGRAMS = eet_basic eet_file eet_data_simple eet_data_nested eet_data_file_descriptor_01 eet_data_file_descriptor_02 eet_data_cipher_decipher + +eet_basic_SOURCES = eet-basic.c +eet_basic_LDADD = $(top_builddir)/src/lib/libeet.la @EET_LIBS@ + +eet_file_SOURCES = eet-file.c +eet_file_LDADD = $(top_builddir)/src/lib/libeet.la @EET_LIBS@ + +eet_data_simple_SOURCES = eet-data-simple.c +eet_data_simple_LDADD = $(top_builddir)/src/lib/libeet.la @EET_LIBS@ + +eet_data_nested_SOURCES = eet-data-nested.c +eet_data_nested_LDADD = $(top_builddir)/src/lib/libeet.la @EET_LIBS@ + +eet_data_file_descriptor_01_SOURCES = eet-data-file_descriptor_01.c +eet_data_file_descriptor_01_LDADD = $(top_builddir)/src/lib/libeet.la @EET_LIBS@ + +eet_data_file_descriptor_02_SOURCES = eet-data-file_descriptor_02.c +eet_data_file_descriptor_02_LDADD = $(top_builddir)/src/lib/libeet.la @EET_LIBS@ + +eet_data_cipher_decipher_SOURCES = eet-data-cipher_decipher.c +eet_data_cipher_decipher_LDADD = $(top_builddir)/src/lib/libeet.la @EET_LIBS@ + +endif + +filesdir = $(datadir)/$(PACKAGE)/examples +files_DATA = + +if INSTALL_EXAMPLES + +files_DATA += \ +eet-basic.c \ +eet-file.c \ +eet-data-simple.c \ +eet-data-nested.c \ +eet-data-file_descriptor_01.c \ +eet-data-file_descriptor_02.c \ +eet-data-cipher_decipher.c + +endif diff --git a/src/examples/eet-basic.c b/src/examples/eet-basic.c new file mode 100644 index 0000000..05ff397 --- /dev/null +++ b/src/examples/eet-basic.c @@ -0,0 +1,40 @@ +#include + +int +main(void) +{ + Eet_File *ef; + char *ret; + int size; + char *entries[] = + { + "Entry 1", + "Big text string here compared to others", + "Eet is cool" + }; + + eet_init(); + + // blindly open an file for output and write strings with their NUL char + ef = eet_open("test.eet", EET_FILE_MODE_WRITE); + eet_write(ef, "Entry 1", entries[0], strlen(entries[0]) + 1, 0); + eet_write(ef, "Entry 2", entries[1], strlen(entries[1]) + 1, 1); + eet_write(ef, "Entry 3", entries[2], strlen(entries[2]) + 1, 0); + eet_close(ef); + + // open the file again and blindly get the entries we wrote + ef = eet_open("test.eet", EET_FILE_MODE_READ); + ret = eet_read(ef, "Entry 1", &size); + printf("%s\n", ret); + free(ret); + ret = eet_read(ef, "Entry 2", &size); + printf("%s\n", ret); + free(ret); + ret = eet_read(ef, "Entry 3", &size); + printf("%s\n", ret); + free(ret); + eet_close(ef); + + eet_shutdown(); +} + diff --git a/src/examples/eet-data-cipher_decipher.c b/src/examples/eet-data-cipher_decipher.c new file mode 100644 index 0000000..2ef965c --- /dev/null +++ b/src/examples/eet-data-cipher_decipher.c @@ -0,0 +1,119 @@ +/* + * build: gcc -o eet_data_file_cipher_decipher eet-data-file_cipher_decipher.c `pkg-config --cflags --libs eet eina` + */ + +#include +#include +#include +#include +#include +#include +#include + +int +main(void) +{ + const char *buffer = "Here is a string of data to save !"; + const char *key = "This is a crypto key"; + const char *key_bad = "This is another crypto key"; + + char *file = strdup("/tmp/eet_cipher_example_XXXXX"); + Eet_File *ef; + char *test; + int size; + + eet_init(); + + if (!(file = tmpnam(file))) + { + fprintf( + stderr, "ERROR: could not create temporary file (%s).\n", file); + goto panic; + } + + /* Crypt an eet file. */ + ef = eet_open(file, EET_FILE_MODE_WRITE); + if (!ef) + { + fprintf( + stderr, "ERROR: could not access file (%s).\n", file); + goto error; + } + + if (!eet_write_cipher(ef, "keys/tests", buffer, strlen(buffer) + 1, 0, key)) + { + fprintf( + stderr, "ERROR: could not access file (%s).\n", file); + goto error; + } + + eet_close(ef); + + /* Decrypt an eet file. */ + ef = eet_open(file, EET_FILE_MODE_READ); + if (!ef) + { + fprintf( + stderr, "ERROR: could not access file (%s).\n", file); + goto error; + } + + test = eet_read_cipher(ef, "keys/tests", &size, key); + if (!test) + { + fprintf( + stderr, "ERROR: could decript contents on file %s, with key %s.\n", + file, key); + goto error; + } + + if (size != (int)strlen(buffer) + 1) + { + fprintf( + stderr, "ERROR: something is wrong with the decripted data\n"); + goto error; + } + + if (memcmp(test, buffer, strlen(buffer) + 1) != 0) + { + fprintf( + stderr, "ERROR: something is wrong with the decripted data\n"); + goto error; + } + + eet_close(ef); + + /* Decrypt an eet file, now using our BAD key!! */ + ef = eet_open(file, EET_FILE_MODE_READ); + if (!ef) + { + fprintf( + stderr, "ERROR: could not access file (%s).\n", file); + goto error; + } + + test = eet_read_cipher(ef, "keys/tests", &size, key_bad); + + if (size == (int)strlen(buffer) + 1) + if (memcmp(test, buffer, strlen(buffer) + 1) == 0) + { + fprintf( + stderr, "ERROR: something is wrong with the contents of %s, as" + " we accessed it with a different key and it decripted our" + " information right.\n", file); + goto error; + } + + eet_close(ef); + +error: + if (unlink(file) != 0) + { + fprintf( + stderr, "ERROR: could not unlink file (%s).\n", file); + } + +panic: + eet_shutdown(); +} + diff --git a/src/examples/eet-data-file_descriptor_01.c b/src/examples/eet-data-file_descriptor_01.c new file mode 100644 index 0000000..4b5b75f --- /dev/null +++ b/src/examples/eet-data-file_descriptor_01.c @@ -0,0 +1,529 @@ +/* + * build: gcc -o eet_data_file_descriptor eet-data-file_descriptor.c `pkg-config --cflags --libs eet eina` + */ +#include +#include +#include +#include +#include +#include +#include + +// complex real-world structures based on elmdentica database +typedef struct +{ + const char *screen_name; + const char *name; + const char *message; + unsigned int id; + unsigned int status_id; + unsigned int date; + unsigned int timeline; +} My_Message; + +typedef struct +{ + const char *dm_to; + const char *message; +} My_Post; + +typedef struct +{ + unsigned int id; + const char *name; + Eina_List *messages; + My_Post *posts; + int posts_count; +} My_Account; + +typedef struct +{ + unsigned int version; // it is recommended to use versioned configuration! + Eina_Hash *accounts; +} My_Cache; + +// string that represents the entry in eet file, you might like to have +// different profiles or so in the same file, this is possible with +// different strings +static const char MY_CACHE_FILE_ENTRY[] = "cache"; + +// keep the descriptor static global, so it can be +// shared by different functions (load/save) of this and only this +// file. +static Eet_Data_Descriptor *_my_cache_descriptor; +static Eet_Data_Descriptor *_my_account_descriptor; +static Eet_Data_Descriptor *_my_message_descriptor; +static Eet_Data_Descriptor *_my_post_descriptor; + +// keep file handle alive, so mmap()ed strings are all alive as well +static Eet_File *_my_cache_file = NULL; +static Eet_Dictionary *_my_cache_dict = NULL; + +static void +_my_cache_descriptor_init(void) +{ + Eet_Data_Descriptor_Class eddc; + + // The FILE variant is good for caches and things that are just + // appended, but needs to take care when changing strings and files must + // be kept open so mmap()ed strings will be kept alive. + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, My_Cache); + _my_cache_descriptor = eet_data_descriptor_file_new(&eddc); + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, My_Account); + _my_account_descriptor = eet_data_descriptor_file_new(&eddc); + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, My_Message); + _my_message_descriptor = eet_data_descriptor_file_new(&eddc); + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, My_Post); + _my_post_descriptor = eet_data_descriptor_file_new(&eddc); + + // Describe the members to be saved: + // Use a temporary macro so we don't type a lot, also avoid errors: + +#define ADD_BASIC(member, eet_type) \ + EET_DATA_DESCRIPTOR_ADD_BASIC \ + (_my_message_descriptor, My_Message, # member, member, eet_type) + ADD_BASIC(screen_name, EET_T_STRING); + ADD_BASIC(name, EET_T_STRING); + ADD_BASIC(message, EET_T_STRING); + ADD_BASIC(id, EET_T_UINT); + ADD_BASIC(status_id, EET_T_UINT); + ADD_BASIC(date, EET_T_UINT); + ADD_BASIC(timeline, EET_T_UINT); +#undef ADD_BASIC + +#define ADD_BASIC(member, eet_type) \ + EET_DATA_DESCRIPTOR_ADD_BASIC \ + (_my_post_descriptor, My_Post, # member, member, eet_type) + ADD_BASIC(dm_to, EET_T_STRING); + ADD_BASIC(message, EET_T_STRING); +#undef ADD_BASIC + +#define ADD_BASIC(member, eet_type) \ + EET_DATA_DESCRIPTOR_ADD_BASIC \ + (_my_account_descriptor, My_Account, # member, member, eet_type) + ADD_BASIC(name, EET_T_STRING); + ADD_BASIC(id, EET_T_UINT); +#undef ADD_BASIC + + EET_DATA_DESCRIPTOR_ADD_LIST + (_my_account_descriptor, My_Account, "messages", messages, + _my_message_descriptor); + EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY + (_my_account_descriptor, My_Account, "posts", posts, + _my_post_descriptor); + +#define ADD_BASIC(member, eet_type) \ + EET_DATA_DESCRIPTOR_ADD_BASIC \ + (_my_cache_descriptor, My_Cache, # member, member, eet_type) + ADD_BASIC(version, EET_T_UINT); +#undef ADD_BASIC + + EET_DATA_DESCRIPTOR_ADD_HASH + (_my_cache_descriptor, My_Cache, "accounts", accounts, + _my_account_descriptor); +} /* _my_cache_descriptor_init */ + +static void +_my_cache_descriptor_shutdown(void) +{ + eet_data_descriptor_free(_my_cache_descriptor); + eet_data_descriptor_free(_my_account_descriptor); + eet_data_descriptor_free(_my_message_descriptor); + eet_data_descriptor_free(_my_post_descriptor); +} /* _my_cache_descriptor_shutdown */ + +// need to check if the pointer came from mmaped area in eet_dictionary +// or it was allocated with eina_stringshare_add() +static void +_eet_string_free(const char *str) +{ + if (!str) + return; + + if ((_my_cache_dict) && (eet_dictionary_string_check(_my_cache_dict, str))) + return; + + eina_stringshare_del(str); +} /* _eet_string_free */ + +static My_Message * +_my_message_new(const char *message) +{ + My_Message *msg = calloc(1, sizeof(My_Message)); + if (!msg) + { + fprintf(stderr, "ERROR: could not calloc My_Message\n"); + return NULL; + } + + msg->message = eina_stringshare_add(message); + return msg; +} /* _my_message_new */ + +static void +_my_message_free(My_Message *msg) +{ + _eet_string_free(msg->screen_name); + _eet_string_free(msg->name); + _eet_string_free(msg->message); + free(msg); +} /* _my_message_free */ + +static Eina_Bool +_my_post_add(My_Account *acc, + const char *message) +{ + int new_count = acc->posts_count + 1; + My_Post *post = realloc(acc->posts, new_count * sizeof(My_Post)); + if (!post) + { + fprintf(stderr, "ERROR: could add My_Post\n"); + return EINA_FALSE; + } + + post[acc->posts_count].message = eina_stringshare_add(message); + post[acc->posts_count].dm_to = NULL; + acc->posts_count = new_count; + acc->posts = post; + return EINA_TRUE; +} /* _my_post_new */ + +static void +_my_post_free(My_Post *post) +{ + _eet_string_free(post->dm_to); + _eet_string_free(post->message); +} /* _my_post_free */ + +static My_Account * +_my_account_new(const char *name) +{ + My_Account *acc = calloc(1, sizeof(My_Account)); + if (!acc) + { + fprintf(stderr, "ERROR: could not calloc My_Account\n"); + return NULL; + } + + acc->name = eina_stringshare_add(name); + return acc; +} /* _my_account_new */ + +static void +_my_account_free(My_Account *acc) +{ + My_Message *m; + int i; + + _eet_string_free(acc->name); + + EINA_LIST_FREE(acc->messages, m) + _my_message_free(m); + + for (i = 0; i < acc->posts_count; i++) + _my_post_free(&acc->posts[i]); + free(acc->posts); + + free(acc); +} /* _my_account_free */ + +static My_Cache * +_my_cache_new(void) +{ + My_Cache *my_cache = calloc(1, sizeof(My_Cache)); + if (!my_cache) + { + fprintf(stderr, "ERROR: could not calloc My_Cache\n"); + return NULL; + } + + my_cache->accounts = eina_hash_string_small_new(NULL); + + my_cache->version = 1; + return my_cache; +} /* _my_cache_new */ + +static Eina_Bool +_my_cache_account_free_cb(const Eina_Hash *hash, + const void *key, + void *data, + void *fdata) +{ + _my_account_free(data); + return EINA_TRUE; +} + +static void +_my_cache_free(My_Cache *my_cache) +{ + My_Account *acc; + eina_hash_foreach(my_cache->accounts, _my_cache_account_free_cb, NULL); + eina_hash_free(my_cache->accounts); + free(my_cache); +} /* _my_cache_free */ + +static My_Account * +_my_cache_account_find(My_Cache *my_cache, + const char *name) +{ + return eina_hash_find(my_cache->accounts, name); +} /* _my_cache_account_find */ + +static My_Cache * +_my_cache_load(const char *filename) +{ + My_Cache *my_cache; + Eet_File *ef = eet_open(filename, EET_FILE_MODE_READ); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for read\n", filename); + return NULL; + } + + my_cache = eet_data_read(ef, _my_cache_descriptor, MY_CACHE_FILE_ENTRY); + if (!my_cache) + { + eet_close(ef); + return NULL; + } + + if (my_cache->version < 1) + { + fprintf(stderr, + "WARNING: version %#x was too old, upgrading it to %#x\n", + my_cache->version, 1); + + my_cache->version = 1; + } + + if (_my_cache_file) + eet_close(_my_cache_file); + + _my_cache_file = ef; + _my_cache_dict = eet_dictionary_get(ef); + + return my_cache; +} /* _my_cache_load */ + +static Eina_Bool +_my_cache_save(const My_Cache *my_cache, + const char *filename) +{ + char tmp[PATH_MAX]; + Eet_File *ef; + Eina_Bool ret; + unsigned int i, len; + struct stat st; + + len = eina_strlcpy(tmp, filename, sizeof(tmp)); + if (len + 12 >= (int)sizeof(tmp)) + { + fprintf(stderr, "ERROR: file name is too big: %s\n", filename); + return EINA_FALSE; + } + + i = 0; + do + { + snprintf(tmp + len, 12, ".%u", i); + i++; + } + while (stat(tmp, &st) == 0); + + ef = eet_open(tmp, EET_FILE_MODE_WRITE); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for write\n", tmp); + return EINA_FALSE; + } + + ret = eet_data_write + (ef, _my_cache_descriptor, MY_CACHE_FILE_ENTRY, my_cache, EINA_TRUE); + + // VERY IMPORTANT NOTE: + // after eet_close(), all strings mmaped from file will be GONE, invalid! + // you'll need to free the old cache and open the new one. + // For cache this is okay, as you should be saving not so often or just + // at end. + // + // This is a trade off, you save memory by using mmap()ed strings, but + // you have to care about this. + eet_close(ef); + + if (ret) + { + unlink(filename); + rename(tmp, filename); + } + + return ret; +} /* _my_cache_save */ + +int +main(int argc, + char *argv[]) +{ + My_Cache *my_cache; + const Eina_List *l_acc; + Eina_Iterator *it; + My_Account *acc; + int ret = 0; + + if (argc < 3) + { + fprintf(stderr, + "Usage:\n\t%s [action] [action-params]\n\n" + "Where actions and their parameters:\n" + "\tacc \n" + "\tpost \n" + "\tmessage \n" + "\n", + argv[0]); + return -1; + } + + eina_init(); + eet_init(); + _my_cache_descriptor_init(); + + my_cache = _my_cache_load(argv[1]); + if (!my_cache) + { + printf("creating new cache.\n"); + my_cache = _my_cache_new(); + if (!my_cache) + { + ret = -2; + goto end; + } + } + + if (argc > 3) + { + if (strcmp(argv[3], "acc") == 0) + { + if (argc == 5) + { + My_Account *acc = _my_cache_account_find(my_cache, argv[4]); + if (!acc) + { + acc = _my_account_new(argv[4]); + eina_hash_direct_add(my_cache->accounts, acc->name, acc); + } + else + fprintf(stderr, "ERROR: account '%s' already exists.\n", + argv[4]); + } + else + fprintf(stderr, + "ERROR: wrong number of parameters (%d).\n", + argc); + } + else if (strcmp(argv[3], "post") == 0) + { + if (argc == 6) + { + My_Account *acc = _my_cache_account_find(my_cache, argv[4]); + if (acc) + { + _my_post_add(acc, argv[5]); + } + else + fprintf(stderr, "ERROR: unknown account: '%s'\n", argv[4]); + } + else + fprintf(stderr, + "ERROR: wrong number of parameters (%d).\n", + argc); + } + else if (strcmp(argv[3], "message") == 0) + { + if (argc == 6) + { + My_Account *acc = _my_cache_account_find(my_cache, argv[4]); + if (acc) + { + My_Message *msg = _my_message_new(argv[5]); + acc->messages = eina_list_append(acc->messages, msg); + } + else + fprintf(stderr, "ERROR: unknown account: '%s'\n", argv[4]); + } + else + fprintf(stderr, + "ERROR: wrong number of parameters (%d).\n", + argc); + } + else + fprintf(stderr, "ERROR: unknown action '%s'\n", argv[2]); + } + + printf("My_Cache:\n" + "\tversion.: %#x\n" + "\taccounts: %u\n", + my_cache->version, + eina_hash_population(my_cache->accounts)); + it = eina_hash_iterator_data_new(my_cache->accounts); + EINA_ITERATOR_FOREACH(it, acc) + { + const My_Post *post; + + printf("\t > %-#8x '%.20s' stats: m=%u, p=%u\n", + acc->id, acc->name ? acc->name : "", + eina_list_count(acc->messages), + acc->posts_count); + + if (eina_list_count(acc->messages)) + { + const Eina_List *l; + const My_Message *msg; + printf("\t |messages:\n"); + + EINA_LIST_FOREACH(acc->messages, l, msg) + { + printf("\t | %-8x '%s' [%s]: '%.20s'\n", + msg->id, + msg->name ? msg->name : "", + msg->screen_name ? msg->screen_name : "", + msg->message ? msg->message : ""); + } + } + + if (acc->posts_count) + { + const My_Post *post; + int i; + printf("\t |posts:\n"); + + for (i = 0; i < acc->posts_count; i++) + { + post = &acc->posts[i]; + if (post->dm_to) + printf("\t | @%s: '%.20s'\n", post->dm_to, post->message); + else + printf("\t | '%.20s'\n", post->message); + } + } + + printf("\n"); + } + eina_iterator_free(it); + + if (!_my_cache_save(my_cache, argv[2])) + ret = -3; + + _my_cache_free(my_cache); + +end: + if (_my_cache_file) + eet_close(_my_cache_file); + _my_cache_descriptor_shutdown(); + eet_shutdown(); + eina_shutdown(); + + return ret; +} /* main */ + diff --git a/src/examples/eet-data-file_descriptor_02.c b/src/examples/eet-data-file_descriptor_02.c new file mode 100644 index 0000000..65ba79e --- /dev/null +++ b/src/examples/eet-data-file_descriptor_02.c @@ -0,0 +1,944 @@ +/* + * build: gcc -o eet_data_file_descriptor_02 eet-data-file_descriptor_02.c `pkg-config --cflags --libs eet eina` + */ + +#include +#include +#include +#include +#include +#include +#include + +typedef enum _Example_Data_Type Example_Data_Type; +typedef struct _Example_Variant_Type Example_Variant_Type; +typedef struct _Example_Variant Example_Variant; +typedef struct _Example_Union Example_Union; +typedef struct _Example_Struct1 Example_Struct1; +typedef struct _Example_Struct2 Example_Struct2; +typedef struct _Example_Struct3 Example_Struct3; +typedef struct _Example_Lists Example_Lists; + +enum _Example_Data_Type +{ + EET_UNKNOWN = 0, + EET_STRUCT1, + EET_STRUCT2, + EET_STRUCT3 +}; + +struct +{ + Example_Data_Type u; + const char *name; +} eet_mapping[] = { + { EET_STRUCT1, "ST1" }, + { EET_STRUCT2, "ST2" }, + { EET_STRUCT3, "ST3" }, + { EET_UNKNOWN, NULL } +}; + +struct _Example_Struct1 +{ + double val1; + int stuff; + const char *s1; +}; + +struct _Example_Struct2 +{ + Eina_Bool b1; + unsigned long long v1; +}; + +struct _Example_Struct3 +{ + int body; +}; + +struct _Example_Union +{ + Example_Data_Type type; + + union { + Example_Struct1 st1; + Example_Struct2 st2; + Example_Struct3 st3; + } u; +}; + +struct _Example_Variant_Type +{ + const char *type; + Eina_Bool unknow : 1; +}; + +struct _Example_Variant +{ + Example_Variant_Type t; + + void *data; /* differently than the union type, we + * don't need to pre-allocate the memory + * for the field*/ +}; + +struct _Example_Lists +{ + Eina_List *union_list; + Eina_List *variant_list; +}; + +static void +_st1_set(Example_Struct1 *st1, + double v1, + int v2, + const char *v3) +{ + st1->val1 = v1; + st1->stuff = v2; + st1->s1 = v3; +} /* _st1_set */ + +static void +_st2_set(Example_Struct2 *st2, + Eina_Bool v1, + unsigned long long v2) +{ + st2->b1 = v1; + st2->v1 = v2; +} /* _st2_set */ + +static void +_st3_set(Example_Struct3 *st3, + int v1) +{ + st3->body = v1; +} /* _st3_set */ + +static const char * +/* union + type_get() */ +_union_type_get(const void *data, + Eina_Bool *unknow) +{ + const Example_Data_Type *u = data; + int i; + + if (unknow) + *unknow = EINA_FALSE; + + for (i = 0; eet_mapping[i].name != NULL; ++i) + if (*u == eet_mapping[i].u) + return eet_mapping[i].name; + + if (unknow) + *unknow = EINA_TRUE; + + return NULL; +} /* _union_type_get */ + +static Eina_Bool +_union_type_set(const char *type, + void *data, + Eina_Bool unknow) +{ + Example_Data_Type *u = data; + int i; + + if (unknow) + return EINA_FALSE; + + for (i = 0; eet_mapping[i].name != NULL; ++i) + if (strcmp(eet_mapping[i].name, type) == 0) + { + *u = eet_mapping[i].u; + return EINA_TRUE; + } + + return EINA_FALSE; +} /* _union_type_set */ + +static const char * +_variant_type_get(const void *data, + Eina_Bool *unknow) +{ + const Example_Variant_Type *type = data; + int i; + + if (unknow) + *unknow = type->unknow; + + for (i = 0; eet_mapping[i].name != NULL; ++i) + if (strcmp(type->type, eet_mapping[i].name) == 0) + return eet_mapping[i].name; + + if (unknow) + *unknow = EINA_FALSE; + + return type->type; +} /* _variant_type_get */ + +static Eina_Bool +_variant_type_set(const char *type, + void *data, + Eina_Bool unknow) +{ + Example_Variant_Type *vt = data; + + vt->type = type; + vt->unknow = unknow; + return EINA_TRUE; +} /* _variant_type_set */ + +static Eet_Data_Descriptor * +_st1_dd(void) +{ + Eet_Data_Descriptor_Class eddc; + Eet_Data_Descriptor *res; + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Struct1); + res = eet_data_descriptor_file_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC( + res, Example_Struct1, "val1", val1, EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC( + res, Example_Struct1, "stuff", stuff, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC( + res, Example_Struct1, "s1", s1, EET_T_STRING); + + return res; +} /* _st1_dd */ + +static Eet_Data_Descriptor * +_st2_dd(void) +{ + Eet_Data_Descriptor_Class eddc; + Eet_Data_Descriptor *res; + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Struct2); + res = eet_data_descriptor_file_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC( + res, Example_Struct2, "b1", b1, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC( + res, Example_Struct2, "v1", v1, EET_T_ULONG_LONG); + + return res; +} /* _st2_dd */ + +static Eet_Data_Descriptor * +_st3_dd(void) +{ + Eet_Data_Descriptor_Class eddc; + Eet_Data_Descriptor *res; + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Struct3); + res = eet_data_descriptor_file_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC( + res, Example_Struct3, "body", body, EET_T_INT); + + return res; +} /* _st3_dd */ + +/* string that represents the entry in the eet file. you might like to + * have different profiles or so in the same file, this is possible + * with different strings + */ +static const char CACHE_FILE_ENTRY[] = "cache"; + +/* keep the descriptor static global, so it can be shared by different + * functions (load/save) of this and only this file. + */ +static Eet_Data_Descriptor *_lists_descriptor; +static Eet_Data_Descriptor *_struct_1_descriptor; +static Eet_Data_Descriptor *_struct_2_descriptor; +static Eet_Data_Descriptor *_struct_3_descriptor; +static Eet_Data_Descriptor *_union_descriptor; +static Eet_Data_Descriptor *_variant_descriptor; +static Eet_Data_Descriptor *_union_unified_descriptor; +static Eet_Data_Descriptor *_variant_unified_descriptor; + +/* keep file handle alive, so mmap()ed strings are all alive as + * well */ +static Eet_File *_cache_file = NULL; +static Eet_Dictionary *_cache_dict = NULL; + +static void +/* declaring types */ +_data_descriptors_init(void) +{ + Eet_Data_Descriptor_Class eddc; + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Lists); + _lists_descriptor = eet_data_descriptor_file_new(&eddc); + + _struct_1_descriptor = _st1_dd(); + _struct_2_descriptor = _st2_dd(); + _struct_3_descriptor = _st3_dd(); + + /* for union */ + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Union); + _union_descriptor = eet_data_descriptor_file_new(&eddc); + + eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION; + eddc.func.type_get = _union_type_get; + eddc.func.type_set = _union_type_set; + _union_unified_descriptor = eet_data_descriptor_file_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_MAPPING( + _union_unified_descriptor, "ST1", _struct_1_descriptor); + EET_DATA_DESCRIPTOR_ADD_MAPPING( + _union_unified_descriptor, "ST2", _struct_2_descriptor); + EET_DATA_DESCRIPTOR_ADD_MAPPING( + _union_unified_descriptor, "ST3", _struct_3_descriptor); + + EET_DATA_DESCRIPTOR_ADD_UNION( + _union_descriptor, Example_Union, "u", u, type, + _union_unified_descriptor); + + EET_DATA_DESCRIPTOR_ADD_LIST( + _lists_descriptor, Example_Lists, "union_list", union_list, + _union_descriptor); + + /* for variant */ + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Example_Variant); + _variant_descriptor = eet_data_descriptor_file_new(&eddc); + + eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION; + eddc.func.type_get = _variant_type_get; + eddc.func.type_set = _variant_type_set; + _variant_unified_descriptor = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_MAPPING( + _variant_unified_descriptor, "ST1", _struct_1_descriptor); + EET_DATA_DESCRIPTOR_ADD_MAPPING( + _variant_unified_descriptor, "ST2", _struct_2_descriptor); + EET_DATA_DESCRIPTOR_ADD_MAPPING( + _variant_unified_descriptor, "ST3", _struct_3_descriptor); + + EET_DATA_DESCRIPTOR_ADD_VARIANT( + _variant_descriptor, Example_Variant, "data", data, t, + _variant_unified_descriptor); + + EET_DATA_DESCRIPTOR_ADD_LIST( + _lists_descriptor, Example_Lists, "variant_list", variant_list, + _variant_descriptor); +} /* _data_descriptors_init */ + +static void +_data_descriptors_shutdown(void) +{ + eet_data_descriptor_free(_lists_descriptor); + eet_data_descriptor_free(_struct_1_descriptor); + eet_data_descriptor_free(_struct_2_descriptor); + eet_data_descriptor_free(_struct_3_descriptor); + eet_data_descriptor_free(_union_descriptor); + eet_data_descriptor_free(_variant_descriptor); + eet_data_descriptor_free(_union_unified_descriptor); + eet_data_descriptor_free(_variant_unified_descriptor); +} /* _data_descriptors_shutdown */ + +/* need to check if the pointer came from mmap()ed area in + * eet_dictionary or it was allocated with eina_stringshare_add() + */ +static void +_string_free(const char *str) +{ + if (!str) + return; + + if ((_cache_dict) && (eet_dictionary_string_check(_cache_dict, str))) + return; + + eina_stringshare_del(str); +} /* _string_free */ + +static Example_Union * +_union_1_new(const char *v1, + const char *v2, + const char *v3) +{ + Example_Union *un = calloc(1, sizeof(Example_Union)); + if (!un) + { + fprintf( + stderr, "ERROR: could not allocate an Example_Union struct.\n"); + return NULL; + } + + un->type = EET_STRUCT1; + _st1_set(&(un->u.st1), atof(v1), atoi(v2), eina_stringshare_add(v3)); + + return un; +} + +static Example_Union * +_union_2_new(const char *v1, + const char *v2) +{ + Example_Union *un = calloc(1, sizeof(Example_Union)); + if (!un) + { + fprintf( + stderr, "ERROR: could not allocate an Example_Union struct.\n"); + return NULL; + } + + un->type = EET_STRUCT2; + _st2_set(&(un->u.st2), atoi(v1), atoi(v2)); + + return un; +} + +static Example_Union * +_union_3_new(const char *v1) +{ + Example_Union *un = calloc(1, sizeof(Example_Union)); + if (!un) + { + fprintf( + stderr, "ERROR: could not allocate an Example_Union struct.\n"); + return NULL; + } + + un->type = EET_STRUCT3; + _st3_set(&(un->u.st3), atoi(v1)); + + return un; +} + +static Example_Variant * +_variant_1_new(const char *v1, + const char *v2, + const char *v3) +{ + Example_Struct1 *st1; + Example_Variant *va = calloc(1, sizeof(Example_Variant)); + if (!va) + { + fprintf( + stderr, "ERROR: could not allocate an Example_Variant struct.\n"); + return NULL; + } + + va = calloc(1, sizeof (Example_Variant)); + va->t.type = eet_mapping[0].name; + st1 = calloc(1, sizeof (Example_Struct1)); + _st1_set(st1, atof(v1), atoi(v2), eina_stringshare_add(v3)); + va->data = st1; + + return va; +} + +static Example_Variant * +_variant_2_new(const char *v1, + const char *v2) +{ + printf("varinant 2 new\n"); + + Example_Struct2 *st2; + Example_Variant *va = calloc(1, sizeof(Example_Variant)); + if (!va) + { + fprintf( + stderr, "ERROR: could not allocate an Example_Variant struct.\n"); + return NULL; + } + + va = calloc(1, sizeof (Example_Variant)); + + va->t.type = eet_mapping[1].name; + + printf("type gets %s\n", va->t.type); + + st2 = calloc(1, sizeof (Example_Struct2)); + _st2_set(st2, atoi(v1), atoi(v2)); + va->data = st2; + + return va; +} + +static Example_Variant * +_variant_3_new(const char *v1) +{ + Example_Struct3 *st3; + Example_Variant *va = calloc(1, sizeof(Example_Variant)); + if (!va) + { + fprintf( + stderr, "ERROR: could not allocate an Example_Variant struct.\n"); + return NULL; + } + + va = calloc(1, sizeof (Example_Variant)); + va->t.type = eet_mapping[2].name; + st3 = calloc(1, sizeof (Example_Struct3)); + _st3_set(st3, atoi(v1)); + va->data = st3; + + return va; +} + +static Example_Lists * +_data_new(void) +{ + Example_Lists *example_lists = calloc(1, sizeof(Example_Lists)); + if (!example_lists) + { + fprintf(stderr, "ERROR: could not allocate a Example_Lists struct.\n"); + return NULL; + } + + return example_lists; +} /* _data_new */ + +static void +_union_free(Example_Union *un) +{ + if (un->type == EET_STRUCT1) + { + Example_Struct1 *st1 = &(un->u.st1); + _string_free(st1->s1); + } + + free(un); +} + +static void +_variant_free(Example_Variant *va) +{ + if (!strcmp(va->t.type, eet_mapping[0].name)) + { + Example_Struct1 *st1 = va->data; + _string_free(st1->s1); + } + + free(va->data); + free(va); +} + +static void +_data_free(Example_Lists *cache) +{ + Example_Union *un; + Example_Variant *va; + + EINA_LIST_FREE(cache->union_list, un) + _union_free(un); + + EINA_LIST_FREE(cache->variant_list, va) + _variant_free(va); + + free(cache); +} /* _data_free */ + +static Example_Lists * +_data_load(const char *filename) +{ + Example_Lists *data; + Eet_File *ef = eet_open(filename, EET_FILE_MODE_READ); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for read\n", filename); + return NULL; + } + + data = eet_data_read(ef, _lists_descriptor, CACHE_FILE_ENTRY); + if (!data) + { + eet_close(ef); + return NULL; + } + + if (_cache_file) + eet_close(_cache_file); + + _cache_file = ef; + _cache_dict = eet_dictionary_get(ef); + + return data; +} /* _data_load */ + +static Eina_Bool +_data_save(const Example_Lists *cache, + const char *filename) +{ + char tmp[PATH_MAX]; + Eet_File *ef; + Eina_Bool ret; + unsigned int i, len; + struct stat st; + + len = eina_strlcpy(tmp, filename, sizeof(tmp)); + if (len + 12 >= (int)sizeof(tmp)) + { + fprintf(stderr, "ERROR: file name is too big: %s\n", filename); + return EINA_FALSE; + } + + i = 0; + do + { + snprintf(tmp + len, 12, ".%u", i); + i++; + } + while (stat(tmp, &st) == 0); + + ef = eet_open(tmp, EET_FILE_MODE_WRITE); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for write\n", tmp); + return EINA_FALSE; + } + + ret = eet_data_write + (ef, _lists_descriptor, CACHE_FILE_ENTRY, cache, EINA_TRUE); + + eet_close(ef); + + if (ret) + { + unlink(filename); + rename(tmp, filename); + } + + return ret; +} /* _data_save */ + +static void +_print_union(const Example_Union *un) +{ + printf("\t | type: %s'\n", eet_mapping[un->type - 1].name); + + switch (un->type) + { + case EET_STRUCT1: + printf("\t\t val1: %f\n", un->u.st1.val1); + printf("\t\t stuff: %d\n", un->u.st1.stuff); + printf("\t\t s1: %s\n", un->u.st1.s1); + break; + + case EET_STRUCT2: + printf("\t\t val1: %i\n", un->u.st2.b1); + printf("\t\t stuff: %lli\n", un->u.st2.v1); + break; + + case EET_STRUCT3: + printf("\t\t val1: %i\n", un->u.st3.body); + break; + + default: + return; + } +} + +static void +_print_variant(const Example_Variant *va) +{ + printf("\t | type: %s'\n", va->t.type); + + switch (va->t.type[2]) + { + case '1': + { + Example_Struct1 *st1 = va->data; + + printf("\t\t val1: %f\n", st1->val1); + printf("\t\t stuff: %d\n", st1->stuff); + printf("\t\t s1: %s\n", st1->s1); + } + break; + + case '2': + { + Example_Struct2 *st2 = va->data; + + printf("\t\t val1: %i\n", st2->b1); + printf("\t\t stuff: %lli\n", st2->v1); + } + break; + + case '3': + { + Example_Struct3 *st3 = va->data; + + printf("\t\t val1: %i\n", st3->body); + } + break; + + default: + return; + } +} + +int +main(int argc, + char *argv[]) +{ + Example_Lists *data_lists; + int ret = 0; + + if (argc < 3) + { + fprintf(stderr, + "Usage:\n\t%s [action action-params]\n\n" + "where actions and their parameters are:\n" + "\tunion [fields]\n" + "\tvariant [fields]\n" + "\n", + argv[0]); + return -1; + } + + eina_init(); + eet_init(); + _data_descriptors_init(); + + data_lists = _data_load(argv[1]); + if (!data_lists) + { + printf("Creating new data lists.\n"); + data_lists = _data_new(); + if (!data_lists) + { + ret = -2; + goto end; + } + } + + if (argc > 3) + { + if (strcmp(argv[3], "union") == 0) + { + if (argc > 4) + { + int type = atoi(argv[4]); + Example_Union *un; + + if (type < EET_STRUCT1 || type > EET_STRUCT3) + { + fprintf(stderr, + "ERROR: invalid type parameter (%s).\n", + argv[4]); + goto cont; + } + + switch (type) + { + case 1: + if (argc != 8) + { + fprintf( + stderr, "ERROR: wrong number of parameters" + " (%d).\n", argc); + goto cont; + } + + un = _union_1_new( + argv[5], argv[6], argv[7]); + if (!un) + { + fprintf( + stderr, "ERROR: could not create the " + "requested union.\n"); + goto cont; + } + data_lists->union_list = + eina_list_append(data_lists->union_list, un); + break; + + case 2: + if (argc != 7) + { + fprintf( + stderr, "ERROR: wrong number of parameters" + " (%d).\n", argc); + goto cont; + } + + un = _union_2_new(argv[5], argv[6]); + if (!un) + { + fprintf( + stderr, "ERROR: could not create the " + "requested union.\n"); + goto cont; + } + data_lists->union_list = + eina_list_append(data_lists->union_list, un); + break; + + case 3: + if (argc != 6) + { + fprintf( + stderr, "ERROR: wrong number of parameters" + " (%d).\n", argc); + goto cont; + } + + un = _union_3_new(argv[5]); + if (!un) + { + fprintf( + stderr, "ERROR: could not create the " + "requested union.\n"); + goto cont; + } + data_lists->union_list = + eina_list_append(data_lists->union_list, un); + break; + + default: + fprintf( + stderr, "ERROR: bad type of of struct passed\n"); + goto cont; + } + } + else + fprintf(stderr, + "ERROR: wrong number of parameters (%d).\n", + argc); + } + else if (strcmp(argv[3], "variant") == 0) + { + if (argc > 4) + { + int type = atoi(argv[4]); + Example_Variant *va; + + if (type < EET_STRUCT1 || type > EET_STRUCT3) + { + fprintf(stderr, + "ERROR: invalid type parameter (%s).\n", + argv[4]); + goto cont; + } + + switch (type) + { + case 1: + if (argc != 8) + { + fprintf( + stderr, "ERROR: wrong number of parameters" + " (%d).\n", argc); + goto cont; + } + + va = _variant_1_new( + argv[5], argv[6], argv[7]); + if (!va) + { + fprintf( + stderr, "ERROR: could not create the " + "requested variant.\n"); + goto cont; + } + data_lists->variant_list = + eina_list_append(data_lists->variant_list, va); + break; + + case 2: + if (argc != 7) + { + fprintf( + stderr, "ERROR: wrong number of parameters" + " (%d).\n", argc); + goto cont; + } + + va = _variant_2_new(argv[5], argv[6]); + if (!va) + { + fprintf( + stderr, "ERROR: could not create the " + "requested variant.\n"); + goto cont; + } + data_lists->variant_list = + eina_list_append(data_lists->variant_list, va); + break; + + case 3: + if (argc != 6) + { + fprintf( + stderr, "ERROR: wrong number of parameters" + " (%d).\n", argc); + goto cont; + } + + va = _variant_3_new(argv[5]); + if (!va) + { + fprintf( + stderr, "ERROR: could not create the " + "requested variant.\n"); + goto cont; + } + data_lists->variant_list = + eina_list_append(data_lists->variant_list, va); + break; + + default: + fprintf( + stderr, "ERROR: bad type of of struct passed\n"); + goto cont; + } + } + else + fprintf(stderr, + "ERROR: wrong number of parameters (%d).\n", + argc); + } + else + fprintf(stderr, "ERROR: unknown action '%s'\n", argv[3]); + } + +cont: + printf("Cached data:\n"); + + printf("\tstats: unions=%u, variants=%u\n", + eina_list_count(data_lists->union_list), + eina_list_count(data_lists->variant_list)); + + if (eina_list_count(data_lists->union_list)) + { + const Eina_List *l; + const Example_Union *un; + printf("\t * union list:\n"); + + EINA_LIST_FOREACH(data_lists->union_list, l, un) + { + _print_union(un); + } + } + + if (eina_list_count(data_lists->variant_list)) + { + const Eina_List *l; + const Example_Variant *un; + printf("\t * variant list:\n"); + + EINA_LIST_FOREACH(data_lists->variant_list, l, un) + { + _print_variant(un); + } + } + + printf("\n"); + + if (!_data_save(data_lists, argv[2])) + ret = -3; + + _data_free(data_lists); + +end: + if (_cache_file) + eet_close(_cache_file); + _data_descriptors_shutdown(); + eet_shutdown(); + eina_shutdown(); + + return ret; +} /* main */ + diff --git a/src/examples/eet-data-nested.c b/src/examples/eet-data-nested.c new file mode 100644 index 0000000..a6b0e12 --- /dev/null +++ b/src/examples/eet-data-nested.c @@ -0,0 +1,272 @@ +/* + * build: gcc -o eet_data_nested eet-data-nested.c `pkg-config --cflags --libs eet eina` + */ +#include +#include +#include +#include +#include +#include +#include + +// The struct that will be loaded and saved. +// note that only the members described in the eet_data_descriptor +// will be automatically handled. The other members will have their +// space reserved and zeroed (as it uses calloc()), but not +// saved or loaded from eet files. +typedef struct +{ + unsigned int version; // it is recommended to use versioned configuration! + const char *name; + int id; + int not_saved_value; // example of not saved data inside! + Eina_Bool enabled; + Eina_List *subs; +} My_Conf_Type; + +typedef struct +{ + const char *server; + int port; +} My_Conf_Subtype; + +// string that represents the entry in eet file, you might like to have +// different profiles or so in the same file, this is possible with +// different strings +static const char MY_CONF_FILE_ENTRY[] = "config"; + +// keep the descriptor static global, so it can be +// shared by different functions (load/save) of this and only this +// file. +static Eet_Data_Descriptor *_my_conf_descriptor; +static Eet_Data_Descriptor *_my_conf_sub_descriptor; + +static void +_my_conf_descriptor_init(void) +{ + Eet_Data_Descriptor_Class eddc; + + // The class describe the functions to use to create the type and its + // full allocated size. + // + // Eina types are very convenient, so use them to create the descriptor, + // so we get eina_list, eina_hash and eina_stringshare automatically! + // + // The STREAM variant is better for configuration files as the values + // will likely change a lot. + // + // The other variant, FILE, is good for caches and things that are just + // appended, but needs to take care when changing strings and files must + // be kept open so mmap()ed strings will be kept alive. + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, My_Conf_Type); + _my_conf_descriptor = eet_data_descriptor_stream_new(&eddc); + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, My_Conf_Subtype); + _my_conf_sub_descriptor = eet_data_descriptor_stream_new(&eddc); + + // Describe the members to be saved: + // Use a temporary macro so we don't type a lot, also avoid errors: +#define MY_CONF_ADD_BASIC(member, eet_type) \ + EET_DATA_DESCRIPTOR_ADD_BASIC \ + (_my_conf_descriptor, My_Conf_Type, # member, member, eet_type) +#define MY_CONF_SUB_ADD_BASIC(member, eet_type) \ + EET_DATA_DESCRIPTOR_ADD_BASIC \ + (_my_conf_sub_descriptor, My_Conf_Subtype, # member, member, eet_type) + + MY_CONF_SUB_ADD_BASIC(server, EET_T_STRING); + MY_CONF_SUB_ADD_BASIC(port, EET_T_INT); + + MY_CONF_ADD_BASIC(version, EET_T_UINT); + MY_CONF_ADD_BASIC(name, EET_T_STRING); + MY_CONF_ADD_BASIC(id, EET_T_INT); + MY_CONF_ADD_BASIC(enabled, EET_T_UCHAR); + + // And add the sub descriptor as a linked list at 'subs' in the main struct + EET_DATA_DESCRIPTOR_ADD_LIST + (_my_conf_descriptor, My_Conf_Type, "subs", subs, _my_conf_sub_descriptor); + +#undef MY_CONF_ADD_BASIC +#undef MY_CONF_SUB_ADD_BASIC +} /* _my_conf_descriptor_init */ + +static void +_my_conf_descriptor_shutdown(void) +{ + eet_data_descriptor_free(_my_conf_sub_descriptor); + eet_data_descriptor_free(_my_conf_descriptor); +} /* _my_conf_descriptor_shutdown */ + +static My_Conf_Type * +_my_conf_new(void) +{ + My_Conf_Type *my_conf = calloc(1, sizeof(My_Conf_Type)); + My_Conf_Subtype *sub; + if (!my_conf) + { + fprintf(stderr, "ERROR: could not calloc My_Conf_Type\n"); + return NULL; + } + + my_conf->version = 0x112233; + my_conf->enabled = EINA_TRUE; + + sub = calloc(1, sizeof(My_Conf_Subtype)); + if (sub) + { + sub->server = eina_stringshare_add("my-server.com"); + sub->port = 1234; + my_conf->subs = eina_list_append(my_conf->subs, sub); + } + + return my_conf; +} /* _my_conf_new */ + +static void +_my_conf_free(My_Conf_Type *my_conf) +{ + My_Conf_Subtype *sub; + EINA_LIST_FREE(my_conf->subs, sub) + { + eina_stringshare_del(sub->server); + free(sub); + } + + eina_stringshare_del(my_conf->name); + free(my_conf); +} /* _my_conf_free */ + +static My_Conf_Type * +_my_conf_load(const char *filename) +{ + My_Conf_Type *my_conf; + Eet_File *ef = eet_open(filename, EET_FILE_MODE_READ); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for read\n", filename); + return NULL; + } + + my_conf = eet_data_read(ef, _my_conf_descriptor, MY_CONF_FILE_ENTRY); + if (!my_conf) + goto end; + + if (my_conf->version < 0x112233) + { + fprintf(stderr, + "WARNING: version %#x was too old, upgrading it to %#x\n", + my_conf->version, 0x112233); + + my_conf->version = 0x112233; + my_conf->enabled = EINA_TRUE; + } + +end: + eet_close(ef); + return my_conf; +} /* _my_conf_load */ + +static Eina_Bool +_my_conf_save(const My_Conf_Type *my_conf, + const char *filename) +{ + char tmp[PATH_MAX]; + Eet_File *ef; + Eina_Bool ret; + unsigned int i, len; + struct stat st; + + len = eina_strlcpy(tmp, filename, sizeof(tmp)); + if (len + 12 >= (int)sizeof(tmp)) + { + fprintf(stderr, "ERROR: file name is too big: %s\n", filename); + return EINA_FALSE; + } + + i = 0; + do + { + snprintf(tmp + len, 12, ".%u", i); + i++; + } + while (stat(tmp, &st) == 0); + + ef = eet_open(tmp, EET_FILE_MODE_WRITE); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for write\n", tmp); + return EINA_FALSE; + } + + ret = eet_data_write + (ef, _my_conf_descriptor, MY_CONF_FILE_ENTRY, my_conf, EINA_TRUE); + eet_close(ef); + + if (ret) + { + unlink(filename); + rename(tmp, filename); + } + + return ret; +} /* _my_conf_save */ + +int +main(int argc, + char *argv[]) +{ + My_Conf_Type *my_conf; + const My_Conf_Subtype *sub; + const Eina_List *l; + int ret = 0; + + if (argc != 3) + { + fprintf(stderr, "Usage:\n\t%s \n\n", argv[0]); + return -1; + } + + eina_init(); + eet_init(); + _my_conf_descriptor_init(); + + my_conf = _my_conf_load(argv[1]); + if (!my_conf) + { + printf("creating new configuration.\n"); + my_conf = _my_conf_new(); + if (!my_conf) + { + ret = -2; + goto end; + } + } + + printf("My_Conf_Type:\n" + "\tversion: %#x\n" + "\tname...: '%s'\n" + "\tid.....: %d\n" + "\tenabled: %hhu\n" + "\tsubs...:\n", + my_conf->version, + my_conf->name ? my_conf->name : "", + my_conf->id, + my_conf->enabled); + + EINA_LIST_FOREACH(my_conf->subs, l, sub) + printf("\t\tserver: '%s', port: %d\n", + sub->server ? sub->server : "", + sub->port); + + if (!_my_conf_save(my_conf, argv[2])) + ret = -3; + + _my_conf_free(my_conf); + +end: + _my_conf_descriptor_shutdown(); + eet_shutdown(); + eina_shutdown(); + + return ret; +} /* main */ + diff --git a/src/examples/eet-data-simple.c b/src/examples/eet-data-simple.c new file mode 100644 index 0000000..1951fc0 --- /dev/null +++ b/src/examples/eet-data-simple.c @@ -0,0 +1,224 @@ +/* + * build: gcc -o eet_data_simple eet-data-simple.c `pkg-config --cflags --libs eet eina` + */ +#include +#include +#include +#include +#include +#include +#include + +// The struct that will be loaded and saved. +// note that only the members described in the eet_data_descriptor +// will be automatically handled. The other members will have their +// space reserved and zeroed (as it uses calloc()), but not +// saved or loaded from eet files. +typedef struct +{ + unsigned int version; // it is recommended to use versioned configuration! + const char *name; + int id; + int not_saved_value; // example of not saved data inside! + Eina_Bool enabled; +} My_Conf_Type; + +// string that represents the entry in eet file, you might like to have +// different profiles or so in the same file, this is possible with +// different strings +static const char MY_CONF_FILE_ENTRY[] = "config"; + +// keep the descriptor static global, so it can be +// shared by different functions (load/save) of this and only this +// file. +static Eet_Data_Descriptor *_my_conf_descriptor; + +static void +_my_conf_descriptor_init(void) +{ + Eet_Data_Descriptor_Class eddc; + + // The class describe the functions to use to create the type and its + // full allocated size. + // + // Eina types are very convenient, so use them to create the descriptor, + // so we get eina_list, eina_hash and eina_stringshare automatically! + // + // The STREAM variant is better for configuration files as the values + // will likely change a lot. + // + // The other variant, FILE, is good for caches and things that are just + // appended, but needs to take care when changing strings and files must + // be kept open so mmap()ed strings will be kept alive. + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, My_Conf_Type); + _my_conf_descriptor = eet_data_descriptor_stream_new(&eddc); + + // Describe the members to be saved: + // Use a temporary macro so we don't type a lot, also avoid errors: +#define MY_CONF_ADD_BASIC(member, eet_type) \ + EET_DATA_DESCRIPTOR_ADD_BASIC \ + (_my_conf_descriptor, My_Conf_Type, # member, member, eet_type) + + MY_CONF_ADD_BASIC(version, EET_T_UINT); + MY_CONF_ADD_BASIC(name, EET_T_STRING); + MY_CONF_ADD_BASIC(id, EET_T_INT); + MY_CONF_ADD_BASIC(enabled, EET_T_UCHAR); + +#undef MY_CONF_ADD_BASIC +} /* _my_conf_descriptor_init */ + +static void +_my_conf_descriptor_shutdown(void) +{ + eet_data_descriptor_free(_my_conf_descriptor); +} /* _my_conf_descriptor_shutdown */ + +static My_Conf_Type * +_my_conf_new(void) +{ + My_Conf_Type *my_conf = calloc(1, sizeof(My_Conf_Type)); + if (!my_conf) + { + fprintf(stderr, "ERROR: could not calloc My_Conf_Type\n"); + return NULL; + } + + my_conf->version = 0x112233; + my_conf->enabled = EINA_TRUE; + return my_conf; +} /* _my_conf_new */ + +static void +_my_conf_free(My_Conf_Type *my_conf) +{ + eina_stringshare_del(my_conf->name); + free(my_conf); +} /* _my_conf_free */ + +static My_Conf_Type * +_my_conf_load(const char *filename) +{ + My_Conf_Type *my_conf; + Eet_File *ef = eet_open(filename, EET_FILE_MODE_READ); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for read\n", filename); + return NULL; + } + + my_conf = eet_data_read(ef, _my_conf_descriptor, MY_CONF_FILE_ENTRY); + if (!my_conf) + goto end; + + if (my_conf->version < 0x112233) + { + fprintf(stderr, + "WARNING: version %#x was too old, upgrading it to %#x\n", + my_conf->version, 0x112233); + + my_conf->version = 0x112233; + my_conf->enabled = EINA_TRUE; + } + +end: + eet_close(ef); + return my_conf; +} /* _my_conf_load */ + +static Eina_Bool +_my_conf_save(const My_Conf_Type *my_conf, + const char *filename) +{ + char tmp[PATH_MAX]; + Eet_File *ef; + Eina_Bool ret; + unsigned int i, len; + struct stat st; + + len = eina_strlcpy(tmp, filename, sizeof(tmp)); + if (len + 12 >= (int)sizeof(tmp)) + { + fprintf(stderr, "ERROR: file name is too big: %s\n", filename); + return EINA_FALSE; + } + + i = 0; + do + { + snprintf(tmp + len, 12, ".%u", i); + i++; + } + while (stat(tmp, &st) == 0); + + ef = eet_open(tmp, EET_FILE_MODE_WRITE); + if (!ef) + { + fprintf(stderr, "ERROR: could not open '%s' for write\n", tmp); + return EINA_FALSE; + } + + ret = eet_data_write + (ef, _my_conf_descriptor, MY_CONF_FILE_ENTRY, my_conf, EINA_TRUE); + eet_close(ef); + + if (ret) + { + unlink(filename); + rename(tmp, filename); + } + + return ret; +} /* _my_conf_save */ + +int +main(int argc, + char *argv[]) +{ + My_Conf_Type *my_conf; + int ret = 0; + + if (argc != 3) + { + fprintf(stderr, "Usage:\n\t%s \n\n", argv[0]); + return -1; + } + + eina_init(); + eet_init(); + _my_conf_descriptor_init(); + + my_conf = _my_conf_load(argv[1]); + if (!my_conf) + { + printf("creating new configuration.\n"); + my_conf = _my_conf_new(); + if (!my_conf) + { + ret = -2; + goto end; + } + } + + printf("My_Conf_Type:\n" + "\tversion: %#x\n" + "\tname...: '%s'\n" + "\tid.....: %d\n" + "\tenabled: %hhu\n", + my_conf->version, + my_conf->name ? my_conf->name : "", + my_conf->id, + my_conf->enabled); + + if (!_my_conf_save(my_conf, argv[2])) + ret = -3; + + _my_conf_free(my_conf); + +end: + _my_conf_descriptor_shutdown(); + eet_shutdown(); + eina_shutdown(); + + return ret; +} /* main */ + diff --git a/src/examples/eet-file.c b/src/examples/eet-file.c new file mode 100644 index 0000000..740c179 --- /dev/null +++ b/src/examples/eet-file.c @@ -0,0 +1,127 @@ +/* + * build: gcc -o eet_file eet-file.c `pkg-config --cflags --libs eet` + */ +#include +#include +#include + +static int +create_eet_file(void) +{ + Eet_File *ef; + char buf[1024], *ptr; + int size, len, i; + const char *some_strings[] = { + "And some more strings", + "spread across several", + "elements of an array!" + }; + const char some_data[] = + "\x1e\xe7\x0f\x42\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x35" + "\x00\x00\x00\xa0\x00\x00\x00\xa0\x00\x00\x00\x24\x00\x00\x00\x11" + "\x00\x00\x00\x00\x2f\x6d\x69\x73\x74\x65\x72\x69\x6f\x75\x73\x2f" + "\x64\x61\x74\x61\x00\x41\x6e\x20\x45\x45\x54\x20\x69\x6e\x73\x69" + "\x64\x65\x20\x6f\x66\x20\x61\x6e\x20\x45\x45\x54\x21\x0a\x54\x68" + "\x69\x73\x20\x77\x61\x73\x6e\x27\x74\x20\x72\x65\x61\x6c\x6c\x79" + "\x20\x75\x73\x65\x66\x75\x6c\x20\x62\x75\x74\x20\x69\x74\x20\x68" + "\x65\x6c\x70\x65\x64\x20\x74\x6f\x20\x73\x68\x6f\x77\x20\x68\x6f" + "\x77\x0a\x74\x6f\x20\x75\x73\x65\x20\x65\x65\x74\x5f\x6d\x65\x6d" + "\x6f\x70\x65\x6e\x5f\x72\x65\x61\x64\x28\x29\x20\x74\x6f\x20\x6f" + "\x70\x65\x6e\x20\x61\x6e\x20\x65\x65\x74\x20\x66\x69\x6c\x65\x20" + "\x66\x72\x6f\x6d\x0a\x64\x61\x74\x61\x20\x61\x6c\x72\x65\x61\x64" + "\x79\x20\x6c\x6f\x61\x64\x65\x64\x20\x69\x6e\x20\x6d\x65\x6d\x6f" + "\x72\x79\x2e\x0a\x00"; + + ef = eet_open("/tmp/my_file.eet", EET_FILE_MODE_WRITE); + if (!ef) return 0; + + strcpy(buf, "Here is a string of data to save!"); + size = eet_write(ef, "/key/to_store/at", buf, sizeof(buf), 1); + if (!size) + { + fprintf(stderr, "Error writing data!\n"); + eet_close(ef); + return 0; + } + len = strlen(buf); + printf("strlen() = %d, eet_write() = %d\n", len, size); + + ptr = buf; + for (i = 0; i < 3; i++) + { + len = strlen(some_strings[i]) + 1; + memcpy(ptr, some_strings[i], len); + ptr += len; + } + eet_write(ef, "/several/strings", buf, sizeof(buf), 1); + eet_sync(ef); + + eet_write(ef, "/some/mysterious/data", some_data, sizeof(some_data) - 1, 1); + + eet_delete(ef, "/several/strings"); + + return eet_close(ef) == EET_ERROR_NONE; +} + +int +main(void) +{ + Eet_File *ef; + char *ret, **list; + int size, num, i; + + eet_init(); + + if (!create_eet_file()) + return -1; + + ef = eet_open("/tmp/my_file.eet", EET_FILE_MODE_READ); + if (!ef) return -1; + + list = eet_list(ef, "*", &num); + if (list) + { + for (i = 0; i < num; i++) + printf("Key stored: %s\n", list[i]); + free(list); + } + + ret = eet_read(ef, "/key/to_store/at", &size); + if (ret) + { + printf("Data read (%i bytes):\n%s\n", size, ret); + free(ret); + } + + ret = eet_read(ef, "/several/strings", &size); + if (ret) + { + printf("More data read (%i bytes):\n%s\n", size, ret); + free(ret); + } + + ret = eet_read(ef, "/some/mysterious/data", &size); + if (ret) + { + Eet_File *ef2; + + ef2 = eet_memopen_read(ret, size); + + num = eet_num_entries(ef2); + printf("Mysterious data has %d entries\n", num); + + printf("Mysterious data:\n%s\n", + (char *)eet_read_direct(ef2, "/mysterious/data", NULL)); + + eet_close(ef2); + + free(ret); + } + + eet_close(ef); + + eet_shutdown(); + + return 0; +} + diff --git a/src/lib/Eet.h b/src/lib/Eet.h index dc7a383..fccfc18 100644 --- a/src/lib/Eet.h +++ b/src/lib/Eet.h @@ -1,37 +1,183 @@ +/** + @brief Eet Data Handling Library Public API Calls + + These routines are used for Eet Library interaction + + @mainpage Eet Library Documentation + + @version 1.7.0 + @date 2000-2012 + + Please see the @ref authors page for contact details. + + @section toc Table of Contents + + @li @ref intro + @li @ref example + @li @ref compiling + @li @ref install + @li @ref next_steps + @li @ref intro_example + + @section intro What is Eet? + + It is a tiny library designed to write an arbitrary set of chunks of data + to a file and optionally compress each chunk (very much like a zip file) + and allow fast random-access reading of the file later on. It does not + do zip as a zip itself has more complexity than is needed, and it was much + simpler to implement this once here. + + Eet is extremely fast, small and simple. Eet files can be very small and + highly compressed, making them very optimal for just sending across the + internet without having to archive, compress or decompress and install them. + They allow for lightning-fast random-access reads once created, making them + perfect for storing data that is written once (or rarely) and read many + times, but the program does not want to have to read it all in at once. + + It also can encode and decode data structures in memory, as well as image + data for saving to Eet files or sending across the network to other + machines, or just writing to arbitrary files on the system. All data is + encoded in a platform independent way and can be written and read by any + architecture. + + @section example A simple example on using Eet + + Here is a simple example on how to use Eet to save a series of strings to a + file and load them again. The advantage of using Eet over just + fprintf() and + fscanf() is that not only can these entries be strings, they need no special + parsing to handle delimiter characters or escaping, they can be binary data, + image data, data structures containing integers, strings, other data + structures, linked lists and much more, without the programmer having to + worry about parsing, and best of all, Eet is very fast. + + This is just a very simple example that doesn't show all of the capabilities + of Eet, but it serves to illustrate its simplicity. + + @include eet-basic.c + + @section compiling How to compile using Eet ? + + Eet is a library your application links to. The procedure for this is very + simple. You simply have to compile your application with the appropriate + compiler flags that the @p pkg-config script outputs. For example: + + Compiling C or C++ files into object files: + + @verbatim + gcc -c -o main.o main.c `pkg-config --cflags eet` + @endverbatim + + Linking object files into a binary executable: + + @verbatim + gcc -o my_application main.o `pkg-config --libs eet` + @endverbatim + + You simply have to make sure that pkg-config is in your shell's PATH (see + the manual page for your appropriate shell) and eet.pc in /usr/lib/pkgconfig + or its path is in the PKG_CONFIG_PATH environment variable. It's that simple + to link and use Eet once you have written your code to use it. + + Since the program is linked to Eet, it is now able to use any advertised + API calls to serialize your data. + + You should make sure you add any extra compile and link flags to your + compile commands that your application may need as well. The above example + is only guaranteed to make Eet add it's own requirements. + + + @section install How is it installed? + + Simple: + + @verbatim + ./configure + make + su - + ... + make install + @endverbatim + + @section next_steps Next Steps + + After you understood what Eet is and installed it in your system you + should proceed understanding the programming interface. We'd recommend + you to take a while to learn Eina + (http://docs.enlightenment.org/auto/eina/) as it is very convenient + and optimized, and Eet provides integration with it. + + Recommended reading: + + @li @ref Eet_File_Group to know the basics to open and save files. + @li @ref Eet_Data_Group to know the convenient way to serialize and + parse your data structures automatically. Just create your + descriptors and let Eet do the work for you. + + @section intro_example Introductory Examples + + @ref Examples + + @todo Document data format for images and data structures. + + */ + +/** + @page authors Authors + @author Carsten Haitzler + @author David Goodlad + @author Cedric Bail + @author Arnaud de Turckheim + @author Luis Felipe Strano Moraes + @author Chidambar Zinnoury + @author Vincent Torri + @author Gustavo Sverzut Barbieri + @author Raphael Kubo da Costa + @author Mathieu Taillefumier + @author Albin "Lutin" Tonnerre + @author Adam Simpkins + @author Mike Blumenkrantz + + Please contact to get in + contact with the developers and maintainers. + */ + #ifndef _EET_H #define _EET_H #include +#include +#include #ifdef EAPI # undef EAPI -#endif +#endif /* ifdef EAPI */ #ifdef _WIN32 # ifdef EFL_EET_BUILD # ifdef DLL_EXPORT # define EAPI __declspec(dllexport) -# else +# else /* ifdef DLL_EXPORT */ # define EAPI # endif /* ! DLL_EXPORT */ -# else +# else /* ifdef EFL_EET_BUILD */ # define EAPI __declspec(dllimport) # endif /* ! EFL_EET_BUILD */ -#else +#else /* ifdef _WIN32 */ # ifdef __GNUC__ # if __GNUC__ >= 4 # define EAPI __attribute__ ((visibility("default"))) -# else +# else /* if __GNUC__ >= 4 */ # define EAPI -# endif -# else +# endif /* if __GNUC__ >= 4 */ +# else /* ifdef __GNUC__ */ # define EAPI -# endif +# endif /* ifdef __GNUC__ */ #endif /* ! _WIN32 */ #ifdef __cplusplus extern "C" { -#endif +#endif /* ifdef __cplusplus */ /** * @file Eet.h @@ -41,1206 +187,4088 @@ extern "C" { * */ -/***************************************************************************/ +#define EET_VERSION_MAJOR 1 +#define EET_VERSION_MINOR 8 +/** + * @typedef Eet_Version + * + * This is the Eet version information structure that can be used at + * runtime to detect which version of eet is being used and adapt + * appropriately as follows for example: + * + * @code + * #if defined(EET_VERSION_MAJOR) && (EET_VERSION_MAJOR >= 1) && defined(EET_VERSION_MINOR) && (EET_VERSION_MINOR > 2) + * printf("Eet version: %i.%i.%i\n", + * eet_version->major, + * eet_version->minor, + * eet_version->micro); + * if (eet_version->revision > 0) + * { + * printf(" Built from SVN revision # %i\n", eet_version->revision); + * } + * #endif + * @endcode + * + * Note the \#if check can be dropped if your program refuses to compile or + * work with an Eet version less than 1.3.0. + */ +typedef struct _Eet_Version +{ + int major; /** < major (binary or source incompatible changes) */ + int minor; /** < minor (new features, bugfixes, major improvements version) */ + int micro; /** < micro (bugfix, internal improvements, no new features version) */ + int revision; /** < svn revision (0 if a proper release or the svn revision number Eet is built from) */ +} Eet_Version; -#define EET_T_UNKNOW 0 /**< Unknown data encoding type */ -#define EET_T_CHAR 1 /**< Data type: char */ -#define EET_T_SHORT 2 /**< Data type: short */ -#define EET_T_INT 3 /**< Data type: int */ -#define EET_T_LONG_LONG 4 /**< Data type: long long */ -#define EET_T_FLOAT 5 /**< Data type: float */ -#define EET_T_DOUBLE 6 /**< Data type: double */ -#define EET_T_UCHAR 7 /**< Data type: unsigned char */ -#define EET_T_USHORT 8 /**< Data type: unsigned short */ -#define EET_T_UINT 9 /**< Data type: unsigned int */ -#define EET_T_ULONG_LONG 10 /**< Data type: unsigned long long */ -#define EET_T_STRING 11 /**< Data type: char * */ -#define EET_T_INLINED_STRING 12 /**< Data type: char * (but compressed inside the resulting eet) */ -#define EET_T_LAST 13 /**< Last data type */ - -#define EET_G_UNKNOWN 100 /**< Unknown group data encoding type */ -#define EET_G_ARRAY 101 /**< Fixed size array group type */ -#define EET_G_VAR_ARRAY 102 /**< Variable size array group type */ -#define EET_G_LIST 103 /**< Linked list group type */ -#define EET_G_HASH 104 /**< Hash table group type */ -#define EET_G_LAST 105 /**< Last group type */ +EAPI extern Eet_Version *eet_version; -/***************************************************************************/ +/** + * @defgroup Eet_Group Top level functions + * Functions that affect Eet as a whole. + * + * @{ + */ - typedef enum _Eet_File_Mode - { - EET_FILE_MODE_INVALID = -1, - EET_FILE_MODE_READ, - EET_FILE_MODE_WRITE, - EET_FILE_MODE_READ_WRITE - } Eet_File_Mode; - - typedef enum _Eet_Error - { - EET_ERROR_NONE, - EET_ERROR_BAD_OBJECT, - EET_ERROR_EMPTY, - EET_ERROR_NOT_WRITABLE, - EET_ERROR_OUT_OF_MEMORY, - EET_ERROR_WRITE_ERROR, - EET_ERROR_WRITE_ERROR_FILE_TOO_BIG, - EET_ERROR_WRITE_ERROR_IO_ERROR, - EET_ERROR_WRITE_ERROR_OUT_OF_SPACE, - EET_ERROR_WRITE_ERROR_FILE_CLOSED - } Eet_Error; - - typedef struct _Eet_File Eet_File; - typedef struct _Eet_Dictionary Eet_Dictionary; - typedef struct _Eet_Data_Descriptor Eet_Data_Descriptor; - - typedef struct _Eet_Data_Descriptor_Class Eet_Data_Descriptor_Class; - -#define EET_DATA_DESCRIPTOR_CLASS_VERSION 2 - struct _Eet_Data_Descriptor_Class - { - int version; - const char *name; - int size; - struct { - void *(*mem_alloc) (size_t size); - void (*mem_free) (void *mem); - char *(*str_alloc) (const char *str); - void (*str_free) (const char *str); - void *(*list_next) (void *l); - void *(*list_append) (void *l, void *d); - void *(*list_data) (void *l); - void *(*list_free) (void *l); - void (*hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt); - void *(*hash_add) (void *h, const char *k, void *d); - void (*hash_free) (void *h); - char *(*str_direct_alloc) (const char *str); - void (*str_direct_free) (const char *str); - } func; - }; +/** + * @enum _Eet_Error + * All the error identifiers known by Eet. + */ +typedef enum _Eet_Error +{ + EET_ERROR_NONE, /**< No error, it's all fine! */ + EET_ERROR_BAD_OBJECT, /**< Given object or handle is NULL or invalid */ + EET_ERROR_EMPTY, /**< There was nothing to do */ + EET_ERROR_NOT_WRITABLE, /**< Could not write to file or file is #EET_FILE_MODE_READ */ + EET_ERROR_OUT_OF_MEMORY, /**< Could not allocate memory */ + EET_ERROR_WRITE_ERROR, /**< Failed to write data to destination */ + EET_ERROR_WRITE_ERROR_FILE_TOO_BIG, /**< Failed to write file since it is too big */ + EET_ERROR_WRITE_ERROR_IO_ERROR, /**< Failed to write due a generic Input/Output error */ + EET_ERROR_WRITE_ERROR_OUT_OF_SPACE, /**< Failed to write due out of space */ + EET_ERROR_WRITE_ERROR_FILE_CLOSED, /**< Failed to write because file was closed */ + EET_ERROR_MMAP_FAILED, /**< Could not mmap file */ + EET_ERROR_X509_ENCODING_FAILED, /**< Could not encode using X509 */ + EET_ERROR_SIGNATURE_FAILED, /**< Could not validate signature */ + EET_ERROR_INVALID_SIGNATURE, /**< Signature is invalid */ + EET_ERROR_NOT_SIGNED, /**< File or contents are not signed */ + EET_ERROR_NOT_IMPLEMENTED, /**< Function is not implemented */ + EET_ERROR_PRNG_NOT_SEEDED, /**< Could not introduce random seed */ + EET_ERROR_ENCRYPT_FAILED, /**< Could not encrypt contents */ + EET_ERROR_DECRYPT_FAILED /**< Could not decrypt contents */ +} Eet_Error; /**< Eet error identifiers */ -/***************************************************************************/ +/** + * @} + */ + +/** + * @defgroup Eet_Compression Eet Compression Levels + * Compression modes/levels supported by Eet. + * + * @{ + */ - /** - * Initialize the EET library. - * - * @return The new init count. - * - * @since 1.0.0 - */ - EAPI int eet_init(void); - - /** - * Shut down the EET library. - * - * @return The new init count. - * - * @since 1.0.0 - */ - EAPI int eet_shutdown(void); - - /** - * Clear eet cache - * - * Eet didn't free items by default. If you are under memory presure, just - * call this function to recall all memory that are not yet referenced anymore. - * The cache take care of modification on disk. - * - * @since 1.0.0 - */ - EAPI void eet_clearcache(void); - - /** - * Open an eet file on disk, and returns a handle to it. - * @param file The file path to the eet file. eg: "/tmp/file.eet". - * @param mode The mode for opening. Either EET_FILE_MODE_READ, EET_FILE_MODE_WRITE or EET_FILE_MODE_READ_WRITE. - * @return An opened eet file handle. - * - * This function will open an exiting eet file for reading, and build - * the directory table in memory and return a handle to the file, if it - * exists and can be read, and no memory errors occur on the way, otherwise - * NULL will be returned. - * - * It will also open an eet file for writing. This will, if successful, - * delete the original file and replace it with a new empty file, till - * the eet file handle is closed or flushed. If it cannot be opened for - * writing or a memory error occurs, NULL is returned. - * - * You can also open the file for read/write. If you then write a key that - * does not exist it will be created, if the key exists it will be replaced - * by the new data. - * - * Example: - * @code - * #include - * #include - * - * int - * main(int argc, char **argv) - * { - * Eet_File *ef; - * char buf[1024], *ret, **list; - * int size, num, i; - * - * strcpy(buf, "Here is a string of data to save!"); - * - * ef = eet_open("/tmp/my_file.eet", EET_FILE_MODE_WRITE); - * if (!ef) return -1; - * if (!eet_write(ef, "/key/to_store/at", buf, 1024, 1)) - * fprintf(stderr, "Error writing data!\n"); - * eet_close(ef); - * - * ef = eet_open("/tmp/my_file.eet", EET_FILE_MODE_READ); - * if (!ef) return -1; - * list = eet_list(ef, "*", &num); - * if (list) - * { - * for (i = 0; i < num; i++) - * printf("Key stored: %s\n", list[i]); - * free(list); - * } - * ret = eet_read(ef, "/key/to_store/at", &size); - * if (ret) - * { - * printf("Data read (%i bytes):\n%s\n", size, ret); - * free(ret); - * } - * eet_close(ef); - * - * return 0; - * } - * @endcode - * - * @since 1.0.0 - */ - EAPI Eet_File *eet_open(const char *file, Eet_File_Mode mode); - - /** - * Get the mode an Eet_File was opened with. - * @param ef A valid eet file handle. - * @return The mode ef was opened with. - * - * @since 1.0.0 - */ - EAPI Eet_File_Mode eet_mode_get(Eet_File *ef); - - /** - * Close an eet file handle and flush and writes pending. - * @param ef A valid eet file handle. - * - * This function will flush any pending writes to disk if the eet file - * was opened for write, and free all data associated with the file handle - * and file, and close the file. - * - * If the eet file handle is not valid nothing will be done. - * - * @since 1.0.0 - */ - EAPI Eet_Error eet_close(Eet_File *ef); - - - /** - * Return a handle to the shared string dictionary of the Eet file - * @param ef A valid eet file handle. - * @return A handle to the dictionary of the file - * - * This function returns a handle to the dictionary of an Eet file whose - * handle is @p ef, if a dictionary exists. NULL is returned otherwise or - * if the file handle is known to be invalid. - * - * @since 1.0.0 - */ - EAPI Eet_Dictionary *eet_dictionary_get(Eet_File *ef); - - /** - * Check if a given string comes from a given dictionary - * @param ed A valid dictionary handle - * @param string A valid 0 byte terminated C string - * @return 1 if it is in the dictionary, 0 otherwise - * - * This checks the given dictionary to see if the given string is actually - * inside that dictionary (i.e. comes from it) and returns 1 if it does. - * If the dictionary handle is invlide, the string is NULL or the string is - * not in the dictionary, 0 is returned. - * - * @since 1.0.0 - */ - EAPI int eet_dictionary_string_check(Eet_Dictionary *ed, const char *string); - - /** - * Read a specified entry from an eet file and return data - * @param ef A valid eet file handle opened for reading. - * @param name Name of the entry. eg: "/base/file_i_want". - * @param size_ret Number of bytes read from entry and returned. - * @return The data stored in that entry in the eet file. - * - * This function finds an entry in the eet file that is stored under the - * name specified, and returns that data, decompressed, if successful. - * NULL is returned if the lookup fails or if memory errors are - * encountered. It is the job of the calling program to call free() on - * the returned data. The number of bytes in the returned data chunk are - * placed in size_ret. - * - * If the eet file handle is not valid NULL is returned and size_ret is - * filled with 0. - * - * @since 1.0.0 - */ - EAPI void *eet_read(Eet_File *ef, const char *name, int *size_ret); - - /** - * Read a specified entry from an eet file and return data - * @param ef A valid eet file handle opened for reading. - * @param name Name of the entry. eg: "/base/file_i_want". - * @param size_ret Number of bytes read from entry and returned. - * @return The data stored in that entry in the eet file. - * - * This function finds an entry in the eet file that is stored under the - * name specified, and returns that data if not compressed and successful. - * NULL is returned if the lookup fails or if memory errors are - * encountered or if the data is comrpessed. The calling program must never - * call free() on the returned data. The number of bytes in the returned - * data chunk are placed in size_ret. - * - * If the eet file handle is not valid NULL is returned and size_ret is - * filled with 0. - * - * @since 1.0.0 - */ - EAPI const void *eet_read_direct(Eet_File *ef, const char *name, int *size_ret); - - /** - * Write a specified entry to an eet file handle - * @param ef A valid eet file handle opened for writing. - * @param name Name of the entry. eg: "/base/file_i_want". - * @param data Pointer to the data to be stored. - * @param size Length in bytes in the data to be stored. - * @param compress Compression flags (1 == compress, 0 = don't compress). - * @return Success or failure of the write. - * - * This function will write the specified chunk of data to the eet file - * and return greater than 0 on success. 0 will be returned on failure. - * - * The eet file handle must be a valid file handle for an eet file opened - * for writing. If it is not, 0 will be returned and no action will be - * performed. - * - * Name, and data must not be NULL, and size must be > 0. If these - * conditions are not met, 0 will be returned. - * - * The data will be copied (and optionally compressed) in ram, pending - * a flush to disk (it will stay in ram till the eet file handle is - * closed though). - * - * @since 1.0.0 - */ - EAPI int eet_write(Eet_File *ef, const char *name, const void *data, int size, int compress); - - /** - * Delete a specified entry from an Eet file being written or re-written - * @param ef A valid eet file handle opened for writing. - * @param name Name of the entry. eg: "/base/file_i_want". - * @return Success or failure of the delete. - * - * This function will delete the specified chunk of data from the eet file - * and return greater than 0 on success. 0 will be returned on failure. - * - * The eet file handle must be a valid file handle for an eet file opened - * for writing. If it is not, 0 will be returned and no action will be - * performed. - * - * Name, must not be NULL, otherwise 0 will be returned. - * - * @since 1.0.0 - */ - EAPI int eet_delete(Eet_File *ef, const char *name); - - /** - * List all entries in eet file matching shell glob. - * @param ef A valid eet file handle. - * @param glob A shell glob to match against. - * @param count_ret Number of entries found to match. - * @return Pointer to an array of strings. - * - * This function will list all entries in the eet file matching the - * supplied shell glob and return an allocated list of their names, if - * there are any, and if no memory errors occur. - * - * The eet file handle must be valid and glob must not be NULL, or NULL - * will be returned and count_ret will be filled with 0. - * - * The calling program must call free() on the array returned, but NOT - * on the string pointers in the array. They are taken as read-only - * internals from the eet file handle. They are only valid as long as - * the file handle is not closed. When it is closed those pointers in the - * array are now not valid and should not be used. - * - * On success the array returned will have a list of string pointers - * that are the names of the entries that matched, and count_ret will have - * the number of entries in this array placed in it. - * - * Hint: an easy way to list all entries in an eet file is to use a glob - * value of "*". - * - * @since 1.0.0 - */ - EAPI char **eet_list(Eet_File *ef, const char *glob, int *count_ret); - - /** - * Return the number of entries in the specified eet file. - * @param ef A valid eet file handle. - * @return Number of entries in ef or -1 if the number of entries - * cannot be read due to open mode restrictions. - * - * @since 1.0.0 - */ - EAPI int eet_num_entries(Eet_File *ef); +/** + * @enum _Eet_Compression + * All the compression modes known by Eet. + */ -/***************************************************************************/ +typedef enum _Eet_Compression +{ + EET_COMPRESSION_NONE = 0, /**< No compression at all @since 1.7 */ + EET_COMPRESSION_DEFAULT = 1, /**< Default compression (Zlib) @since 1.7 */ + EET_COMPRESSION_LOW = 2, /**< Fast but minimal compression (Zlib) @since 1.7 */ + EET_COMPRESSION_MED = 6, /**< Medium compression level (Zlib) @since 1.7 */ + EET_COMPRESSION_HI = 9, /**< Slow but high compression level (Zlib) @since 1.7 */ + EET_COMPRESSION_VERYFAST = 10, /**< Very fast, but lower compression ratio (LZ4HC) @since 1.7 */ + EET_COMPRESSION_SUPERFAST = 11, /**< Very fast, but lower compression ratio (faster to compress than EET_COMPRESSION_VERYFAST) (LZ4) @since 1.7 */ + + EET_COMPRESSION_LOW2 = 3, /**< Space filler for compatibility. Don't use it @since 1.7 */ + EET_COMPRESSION_MED1 = 4, /**< Space filler for compatibility. Don't use it @since 1.7 */ + EET_COMPRESSION_MED2 = 5, /**< Space filler for compatibility. Don't use it @since 1.7 */ + EET_COMPRESSION_HI1 = 7, /**< Space filler for compatibility. Don't use it @since 1.7 */ + EET_COMPRESSION_HI2 = 8 /**< Space filler for compatibility. Don't use it @since 1.7 */ +} Eet_Compression; /**< Eet compression modes @since 1.7 */ + +/** + * @} + */ - /** - * Read just the header data for an image and dont decode the pixels. - * @param ef A valid eet file handle opened for reading. - * @param name Name of the entry. eg: "/base/file_i_want". - * @param w A pointer to the unsigned int to hold the width in pixels. - * @param h A pointer to the unsigned int to hold the height in pixels. - * @param alpha A pointer to the int to hold the alpha flag. - * @param compress A pointer to the int to hold the compression amount. - * @param quality A pointer to the int to hold the quality amount. - * @param lossy A pointer to the int to hold the lossiness flag. - * @return 1 on successfull decode, 0 otherwise - * - * This function reads an image from an eet file stored under the named - * key in the eet file and return a pointer to the decompressed pixel data. - * - * The other parameters of the image (width, height etc.) are placed into - * the values pointed to (they must be supplied). The pixel data is a linear - * array of pixels starting from the top-left of the image scanning row by - * row from left to right. Each pile is a 32bit value, with the high byte - * being the alpha channel, the next being red, then green, and the low byte - * being blue. The width and height are measured in pixels and will be - * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes - * that the alpha channel is not used. 1 denotes that it is significant. - * Compress is filled with the compression value/amount the image was - * stored with. The quality value is filled with the quality encoding of - * the image file (0 - 100). The lossy flags is either 0 or 1 as to if - * the image was encoded lossily or not. - * - * On success the function returns 1 indicating the header was read and - * decoded properly, or 0 on failure. - * - * @since 1.0.0 - */ - EAPI int eet_data_image_header_read(Eet_File *ef, const char *name, unsigned int *w, unsigned int *h, int *alpha, int *compress, int *quality, int *lossy); - - /** - * Read image data from the named key in the eet file. - * @param ef A valid eet file handle opened for reading. - * @param name Name of the entry. eg: "/base/file_i_want". - * @param w A pointer to the unsigned int to hold the width in pixels. - * @param h A pointer to the unsigned int to hold the height in pixels. - * @param alpha A pointer to the int to hold the alpha flag. - * @param compress A pointer to the int to hold the compression amount. - * @param quality A pointer to the int to hold the quality amount. - * @param lossy A pointer to the int to hold the lossiness flag. - * @return The image pixel data decoded - * - * This function reads an image from an eet file stored under the named - * key in the eet file and return a pointer to the decompressed pixel data. - * - * The other parameters of the image (width, height etc.) are placed into - * the values pointed to (they must be supplied). The pixel data is a linear - * array of pixels starting from the top-left of the image scanning row by - * row from left to right. Each pile is a 32bit value, with the high byte - * being the alpha channel, the next being red, then green, and the low byte - * being blue. The width and height are measured in pixels and will be - * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes - * that the alpha channel is not used. 1 denotes that it is significant. - * Compress is filled with the compression value/amount the image was - * stored with. The quality value is filled with the quality encoding of - * the image file (0 - 100). The lossy flags is either 0 or 1 as to if - * the image was encoded lossily or not. - * - * On success the function returns a pointer to the image data decoded. The - * calling application is responsible for calling free() on the image data - * when it is done with it. On failure NULL is returned and the parameter - * values may not contain any sensible data. - * - * @since 1.0.0 - */ - EAPI void *eet_data_image_read(Eet_File *ef, const char *name, unsigned int *w, unsigned int *h, int *alpha, int *compress, int *quality, int *lossy); - - /** - * Read image data from the named key in the eet file. - * @param ef A valid eet file handle opened for reading. - * @param name Name of the entry. eg: "/base/file_i_want". - * @param src_x The starting x coordinate from where to dump the stream. - * @param src_y The starting y coordinate from where to dump the stream. - * @param d A pointer to the pixel surface. - * @param w The expected width in pixels of the pixel surface to decode. - * @param h The expected height in pixels of the pixel surface to decode. - * @param row_stride The length of a pixels line in the destination surface. - * @param alpha A pointer to the int to hold the alpha flag. - * @param compress A pointer to the int to hold the compression amount. - * @param quality A pointer to the int to hold the quality amount. - * @param lossy A pointer to the int to hold the lossiness flag. - * @return 1 on success, 0 otherwise. - * - * This function reads an image from an eet file stored under the named - * key in the eet file and return a pointer to the decompressed pixel data. - * - * The other parameters of the image (width, height etc.) are placed into - * the values pointed to (they must be supplied). The pixel data is a linear - * array of pixels starting from the top-left of the image scanning row by - * row from left to right. Each pile is a 32bit value, with the high byte - * being the alpha channel, the next being red, then green, and the low byte - * being blue. The width and height are measured in pixels and will be - * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes - * that the alpha channel is not used. 1 denotes that it is significant. - * Compress is filled with the compression value/amount the image was - * stored with. The quality value is filled with the quality encoding of - * the image file (0 - 100). The lossy flags is either 0 or 1 as to if - * the image was encoded lossily or not. - * - * On success the function returns 1, and 0 on failure. On failure the - * parameter values may not contain any sensible data. - * - * @since 1.0.2 - */ - EAPI int eet_data_image_read_to_surface(Eet_File *ef, const char *name, unsigned int src_x, unsigned int src_y, unsigned int *d, unsigned int w, unsigned int h, unsigned int row_stride, int *alpha, int *compress, int *quality, int *lossy); - - /** - * Write image data to the named key in an eet file. - * @param ef A valid eet file handle opened for writing. - * @param name Name of the entry. eg: "/base/file_i_want". - * @param data A pointer to the image pixel data. - * @param w The width of the image in pixels. - * @param h The height of the image in pixels. - * @param alpha The alpha channel flag. - * @param compress The compression amount. - * @param quality The quality encoding amount. - * @param lossy The lossiness flag. - * @return Success if the data was encoded and written or not. - * - * This function takes image pixel data and encodes it in an eet file - * stored under the supplied name key, and returns how many bytes were - * actually written to encode the image data. - * - * The data expected is the same format as returned by eet_data_image_read. - * If this is not the case weird things may happen. Width and height must - * be between 1 and 8000 pixels. The alpha flags can be 0 or 1 (0 meaning - * the alpha values are not useful and 1 meaning they are). Compress can - * be from 0 to 9 (0 meaning no compression, 9 meaning full compression). - * This is only used if the image is not lossily encoded. Quality is used on - * lossy compression and should be a value from 0 to 100. The lossy flag - * can be 0 or 1. 0 means encode losslessly and 1 means to encode with - * image quality loss (but then have a much smaller encoding). - * - * On success this function returns the number of bytes that were required - * to encode the image data, or on failure it returns 0. - * - * @since 1.0.0 - */ - EAPI int eet_data_image_write(Eet_File *ef, const char *name, const void *data, unsigned int w, unsigned int h, int alpha, int compress, int quality, int lossy); - - /** - * Decode Image data header only to get information. - * @param data The encoded pixel data. - * @param size The size, in bytes, of the encoded pixel data. - * @param w A pointer to the unsigned int to hold the width in pixels. - * @param h A pointer to the unsigned int to hold the height in pixels. - * @param alpha A pointer to the int to hold the alpha flag. - * @param compress A pointer to the int to hold the compression amount. - * @param quality A pointer to the int to hold the quality amount. - * @param lossy A pointer to the int to hold the lossiness flag. - * @return 1 on success, 0 on failure. - * - * This function takes encoded pixel data and decodes it into raw RGBA - * pixels on success. - * - * The other parameters of the image (width, height etc.) are placed into - * the values pointed to (they must be supplied). The pixel data is a linear - * array of pixels starting from the top-left of the image scanning row by - * row from left to right. Each pixel is a 32bit value, with the high byte - * being the alpha channel, the next being red, then green, and the low byte - * being blue. The width and height are measured in pixels and will be - * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes - * that the alpha channel is not used. 1 denotes that it is significant. - * Compress is filled with the compression value/amount the image was - * stored with. The quality value is filled with the quality encoding of - * the image file (0 - 100). The lossy flags is either 0 or 1 as to if - * the image was encoded lossily or not. - * - * On success the function returns 1 indicating the header was read and - * decoded properly, or 0 on failure. - * - * @since 1.0.0 - */ - EAPI int eet_data_image_header_decode(const void *data, int size, unsigned int *w, unsigned int *h, int *alpha, int *compress, int *quality, int *lossy); - - /** - * Decode Image data into pixel data. - * @param data The encoded pixel data. - * @param size The size, in bytes, of the encoded pixel data. - * @param w A pointer to the unsigned int to hold the width in pixels. - * @param h A pointer to the unsigned int to hold the height in pixels. - * @param alpha A pointer to the int to hold the alpha flag. - * @param compress A pointer to the int to hold the compression amount. - * @param quality A pointer to the int to hold the quality amount. - * @param lossy A pointer to the int to hold the lossiness flag. - * @return The image pixel data decoded - * - * This function takes encoded pixel data and decodes it into raw RGBA - * pixels on success. - * - * The other parameters of the image (width, height etc.) are placed into - * the values pointed to (they must be supplied). The pixel data is a linear - * array of pixels starting from the top-left of the image scanning row by - * row from left to right. Each pixel is a 32bit value, with the high byte - * being the alpha channel, the next being red, then green, and the low byte - * being blue. The width and height are measured in pixels and will be - * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes - * that the alpha channel is not used. 1 denotes that it is significant. - * Compress is filled with the compression value/amount the image was - * stored with. The quality value is filled with the quality encoding of - * the image file (0 - 100). The lossy flags is either 0 or 1 as to if - * the image was encoded lossily or not. - * - * On success the function returns a pointer to the image data decoded. The - * calling application is responsible for calling free() on the image data - * when it is done with it. On failure NULL is returned and the parameter - * values may not contain any sensible data. - * - * @since 1.0.0 - */ - EAPI void *eet_data_image_decode(const void *data, int size, unsigned int *w, unsigned int *h, int *alpha, int *compress, int *quality, int *lossy); - - /** - * Decode Image data into pixel data. - * @param data The encoded pixel data. - * @param size The size, in bytes, of the encoded pixel data. - * @param src_x The starting x coordinate from where to dump the stream. - * @param src_y The starting y coordinate from where to dump the stream. - * @param d A pointer to the pixel surface. - * @param w The expected width in pixels of the pixel surface to decode. - * @param h The expected height in pixels of the pixel surface to decode. - * @param row_stride The length of a pixels line in the destination surface. - * @param alpha A pointer to the int to hold the alpha flag. - * @param compress A pointer to the int to hold the compression amount. - * @param quality A pointer to the int to hold the quality amount. - * @param lossy A pointer to the int to hold the lossiness flag. - * @return 1 on success, 0 otherwise. - * - * This function takes encoded pixel data and decodes it into raw RGBA - * pixels on success. - * - * The other parameters of the image (alpha, compress etc.) are placed into - * the values pointed to (they must be supplied). The pixel data is a linear - * array of pixels starting from the top-left of the image scanning row by - * row from left to right. Each pixel is a 32bit value, with the high byte - * being the alpha channel, the next being red, then green, and the low byte - * being blue. The width and height are measured in pixels and will be - * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes - * that the alpha channel is not used. 1 denotes that it is significant. - * Compress is filled with the compression value/amount the image was - * stored with. The quality value is filled with the quality encoding of - * the image file (0 - 100). The lossy flags is either 0 or 1 as to if - * the image was encoded lossily or not. - * - * On success the function returns 1, and 0 on failure. On failure the - * parameter values may not contain any sensible data. - * - * @since 1.0.2 - */ - EAPI int eet_data_image_decode_to_surface(const void *data, int size, unsigned int src_x, unsigned int src_y, unsigned int *d, unsigned int w, unsigned int h, unsigned int row_stride, int *alpha, int *compress, int *quality, int *lossy); - - /** - * Encode image data for storage or transmission. - * @param data A pointer to the image pixel data. - * @param size_ret A pointer to an int to hold the size of the returned data. - * @param w The width of the image in pixels. - * @param h The height of the image in pixels. - * @param alpha The alpha channel flag. - * @param compress The compression amount. - * @param quality The quality encoding amount. - * @param lossy The lossiness flag. - * @return The encoded image data. - * - * This function stakes image pixel data and encodes it with compression and - * possible loss of quality (as a trade off for size) for storage or - * transmission to another system. - * - * The data expected is the same format as returned by eet_data_image_read. - * If this is not the case weird things may happen. Width and height must - * be between 1 and 8000 pixels. The alpha flags can be 0 or 1 (0 meaning - * the alpha values are not useful and 1 meaning they are). Compress can - * be from 0 to 9 (0 meaning no compression, 9 meaning full compression). - * This is only used if the image is not lossily encoded. Quality is used on - * lossy compression and should be a value from 0 to 100. The lossy flag - * can be 0 or 1. 0 means encode losslessly and 1 means to encode with - * image quality loss (but then have a much smaller encoding). - * - * On success this function returns a pointer to the encoded data that you - * can free with free() when no longer needed. - * - * @since 1.0.0 - */ - EAPI void *eet_data_image_encode(const void *data, int *size_ret, unsigned int w, unsigned int h, int alpha, int compress, int quality, int lossy); +/** + * Initialize the EET library. + * + * The first time this function is called, it will perform all the internal + * initialization required for the library to function properly and increment + * the initialization counter. Any subsequent call only increment this counter + * and return its new value, so it's safe to call this function more than once. + * + * @return The new init count. Will be 0 if initialization failed. + * + * @since 1.0.0 + * @ingroup Eet_Group + */ +EAPI int +eet_init(void); -/***************************************************************************/ +/** + * Shut down the EET library. + * + * If eet_init() was called more than once for the running application, + * eet_shutdown() will decrement the initialization counter and return its + * new value, without doing anything else. When the counter reaches 0, all + * of the internal elements will be shutdown and any memory used freed. + * + * @return The new init count. + * + * @since 1.0.0 + * @ingroup Eet_Group + */ +EAPI int +eet_shutdown(void); - /** - * Create a new empty data structure descriptor. - * @param name The string name of this data structure (most be a global constant and never change). - * @param size The size of the struct (in bytes). - * @param func_list_next The function to get the next list node. - * @param func_list_append The function to append a member to a list. - * @param func_list_data The function to get the data from a list node. - * @param func_list_free The function to free an entire linked list. - * @param func_hash_foreach The function to iterate through all hash table entries. - * @param func_hash_add The function to add a member to a hash table. - * @param func_hash_free The function to free an entire hash table. - * @return A new empty data descriptor. - * - * This function creates a new data descriptore and returns a handle to the - * new data descriptor. On creation it will be empty, containing no contents - * describing anything other than the shell of the data structure. - * - * You add structure members to the data descriptor using the macros - * EET_DATA_DESCRIPTOR_ADD_BASIC(), EET_DATA_DESCRIPTOR_ADD_SUB() and - * EET_DATA_DESCRIPTOR_ADD_LIST(), depending on what type of member you are - * adding to the description. - * - * Once you have described all the members of a struct you want loaded, or - * saved eet can load and save those members for you, encode them into - * endian-independant serialised data chunks for transmission across a - * a network or more. - * - * The function pointers to the list and hash table functions are only - * needed if you use those data types, else you can pass NULL instead. - * - * Example: - * - * @code - * #include - * #include - * - * typedef struct _blah2 - * { - * char *string; - * } - * Blah2; - * - * typedef struct _blah3 - * { - * char *string; - * } - * Blah3; - * - * typedef struct _blah - * { - * char character; - * short sixteen; - * int integer; - * long long lots; - * float floating; - * double floating_lots; - * char *string; - * Blah2 *blah2; - * Evas_List *blah3; - * } - * Blah; - * - * int - * main(int argc, char **argv) - * { - * Blah blah; - * Blah2 blah2; - * Blah3 blah3; - * Eet_Data_Descriptor *edd, *edd2, *edd3; - * void *data; - * int size; - * FILE *f; - * Blah *blah_in; - * - * edd3 = eet_data_descriptor_new("blah3", sizeof(Blah3), - * evas_list_next, - * evas_list_append, - * evas_list_data, - * evas_list_free, - * evas_hash_foreach, - * evas_hash_add, - * evas_hash_free); - * EET_DATA_DESCRIPTOR_ADD_BASIC(edd3, Blah3, "string3", string, EET_T_STRING); - * - * edd2 = eet_data_descriptor_new("blah2", sizeof(Blah2), - * evas_list_next, - * evas_list_append, - * evas_list_data, - * evas_list_free, - * evas_hash_foreach, - * evas_hash_add, - * evas_hash_free); - * EET_DATA_DESCRIPTOR_ADD_BASIC(edd2, Blah2, "string2", string, EET_T_STRING); - * - * edd = eet_data_descriptor_new("blah", sizeof(Blah), - * evas_list_next, - * evas_list_append, - * evas_list_data, - * evas_list_free, - * evas_hash_foreach, - * evas_hash_add, - * evas_hash_free); - * EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "character", character, EET_T_CHAR); - * EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "sixteen", sixteen, EET_T_SHORT); - * EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "integer", integer, EET_T_INT); - * EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "lots", lots, EET_T_LONG_LONG); - * EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "floating", floating, EET_T_FLOAT); - * EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "floating_lots", floating_lots, EET_T_DOUBLE); - * EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Blah, "string", string, EET_T_STRING); - * EET_DATA_DESCRIPTOR_ADD_SUB(edd, Blah, "blah2", blah2, edd2); - * EET_DATA_DESCRIPTOR_ADD_LIST(edd, Blah, "blah3", blah3, edd3); - * - * blah3.string="PANTS"; - * - * blah2.string="subtype string here!"; - * - * blah.character='7'; - * blah.sixteen=0x7777; - * blah.integer=0xc0def00d; - * blah.lots=0xdeadbeef31337777; - * blah.floating=3.141592654; - * blah.floating_lots=0.777777777777777; - * blah.string="bite me like a turnip"; - * blah.blah2 = &blah2; - * blah.blah3 = evas_list_append(NULL, &blah3); - * blah.blah3 = evas_list_append(blah.blah3, &blah3); - * blah.blah3 = evas_list_append(blah.blah3, &blah3); - * blah.blah3 = evas_list_append(blah.blah3, &blah3); - * blah.blah3 = evas_list_append(blah.blah3, &blah3); - * blah.blah3 = evas_list_append(blah.blah3, &blah3); - * blah.blah3 = evas_list_append(blah.blah3, &blah3); - * - * data = eet_data_descriptor_encode(edd, &blah, &size); - * printf("-----DECODING\n"); - * blah_in = eet_data_descriptor_decode(edd, data, size); - * - * printf("-----DECODED!\n"); - * printf("%c\n", blah_in->character); - * printf("%x\n", (int)blah_in->sixteen); - * printf("%x\n", blah_in->integer); - * printf("%lx\n", blah_in->lots); - * printf("%f\n", (double)blah_in->floating); - * printf("%f\n", (double)blah_in->floating_lots); - * printf("%s\n", blah_in->string); - * printf("%p\n", blah_in->blah2); - * printf(" %s\n", blah_in->blah2->string); - * { - * Evas_List *l; - * - * for (l = blah_in->blah3; l; l = l->next) - * { - * Blah3 *blah3_in; - * - * blah3_in = l->data; - * printf("%p\n", blah3_in); - * printf(" %s\n", blah3_in->string); - * } - * } - * eet_data_descriptor_free(edd); - * eet_data_descriptor_free(edd2); - * eet_data_descriptor_free(edd3); - * - * return 0; - * } - * - * @endcode - * - * @since 1.0.0 - */ - EAPI Eet_Data_Descriptor *eet_data_descriptor_new(const char *name, int size, void *(*func_list_next) (void *l), void *(*func_list_append) (void *l, void *d), void *(*func_list_data) (void *l), void *(*func_list_free) (void *l), void (*func_hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt), void *(*func_hash_add) (void *h, const char *k, void *d), void (*func_hash_free) (void *h)); - /* - * FIXME: - * - * moving to this api from the old above. this will break things when the - * move happens - but be warned - */ - EAPI Eet_Data_Descriptor *eet_data_descriptor2_new(Eet_Data_Descriptor_Class *eddc); - EAPI Eet_Data_Descriptor *eet_data_descriptor3_new(Eet_Data_Descriptor_Class *eddc); - - /** - * This function frees a data descriptor when it is not needed anymore. - * @param edd The data descriptor to free. - * - * This function takes a data descriptor handle as a parameter and frees all - * data allocated for the data descriptor and the handle itself. After this - * call the descriptor is no longer valid. - * - * @since 1.0.0 - */ - EAPI void eet_data_descriptor_free(Eet_Data_Descriptor *edd); - - /** - * This function is an internal used by macros. - * - * This function is used by macros EET_DATA_DESCRIPTOR_ADD_BASIC(), - * EET_DATA_DESCRIPTOR_ADD_SUB() and EET_DATA_DESCRIPTOR_ADD_LIST(). It is - * complex to use by hand and should be left to be used by the macros, and - * thus is not documented. - * - * @since 1.0.0 - */ - EAPI void eet_data_descriptor_element_add(Eet_Data_Descriptor *edd, const char *name, int type, int group_type, int offset, /* int count_offset, */int count, const char *counter_name, Eet_Data_Descriptor *subtype); - - /** - * Read a data structure from an eet file and decodes it. - * @param ef The eet file handle to read from. - * @param edd The data descriptor handle to use when decoding. - * @param name The key the data is stored under in the eet file. - * @return A pointer to the decoded data structure. - * - * This function decodes a data structure stored in an eet file, returning - * a pointer to it if it decoded successfully, or NULL on failure. This - * can save a programmer dozens of hours of work in writing configuration - * file parsing and writing code, as eet does all that work for the program - * and presents a program-friendly data structure, just as the programmer - * likes. Eet can handle members being added or deleted from the data in - * storage and safely zero-fills unfilled members if they were not found - * in the data. It checks sizes and headers whenever it reads data, allowing - * the programmer to not worry about corrupt data. - * - * Once a data structure has been described by the programmer with the - * fields they wish to save or load, storing or retrieving a data structure - * from an eet file, or from a chunk of memory is as simple as a single - * function call. - * - * @since 1.0.0 - */ - EAPI void *eet_data_read(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name); - - /** - * Write a data structure from memory and store in an eet file. - * @param ef The eet file handle to write to. - * @param edd The data descriptor to use when encoding. - * @param name The key to store the data under in the eet file. - * @param data A pointer to the data structure to ssave and encode. - * @param compress Compression flags for storage. - * @return 1 on successful write, 0 on failure. - * - * This function is the reverse of eet_data_read(), saving a data structure - * to an eet file. - * - * @since 1.0.0 - */ - EAPI int eet_data_write(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name, const void *data, int compress); - - /** - * Dump an eet encoded data structure into ascii text - * @param data_in The pointer to the data to decode into a struct. - * @param size_in The size of the data pointed to in bytes. - * @param dumpfunc The function to call passed a string when new data is converted to text - * @param dumpdata The data to pass to the @p dumpfunc callback. - * @return 1 on success, 0 on failure - * - * This function will take a chunk of data encoded by - * eet_data_descriptor_encode() and convert it into human readable ascii text. - * It does this by calling the @p dumpfunc callback for all new text that is - * generated. This callback should append to any existing text buffer and - * will be passed the pointer @p dumpdata as a parameter as well as a string - * with new text to be appended. - * - * Example: - * - * @code - * - * void output(void *data, const char *string) - * { - * printf("%s", string); - * } - * - * void dump(const char *file) - * { - * FILE *f; - * int len; - * void *data; - * - * f = fopen(file, "r"); - * fseek(f, 0, SEEK_END); - * len = ftell(f); - * rewind(f); - * data = malloc(len); - * fread(data, len, 1, f); - * fclose(f); - * eet_data_text_dump(data, len, output, NULL); - * } - * @endcode - * - * @since 1.0.0 - */ - EAPI int eet_data_text_dump(const void *data_in, int size_in, void (*dumpfunc) (void *data, const char *str), void *dumpdata); - - /** - * Take an ascii encoding from eet_data_text_dump() and re-encode in binary. - * @param text The pointer to the string data to parse and encode. - * @param textlen The size of the string in bytes (not including 0 byte terminator). - * @param size_ret This gets filled in with the encoded data blob size in bytes. - * @return The encoded data on success, NULL on failure. - * - * This function will parse the string pointed to by @p text and return - * an encoded data lump the same way eet_data_descriptor_encode() takes an - * in-memory data struct and encodes into a binary blob. @p text is a normal - * C string. - * - * @since 1.0.0 - */ - EAPI void *eet_data_text_undump(const char *text, int textlen, int *size_ret); - - /** - * Dump an eet encoded data structure from an eet file into ascii text - * @param ef A valid eet file handle. - * @param name Name of the entry. eg: "/base/file_i_want". - * @param dumpfunc The function to call passed a string when new data is converted to text - * @param dumpdata The data to pass to the @p dumpfunc callback. - * @return 1 on success, 0 on failure - * - * This function will take an open and valid eet file from eet_open() request - * the data encoded by eet_data_descriptor_encode() corresponding to the key @p name - * and convert it into human readable ascii text. It does this by calling the - * @p dumpfunc callback for all new text that is generated. This callback should - * append to any existing text buffer and will be passed the pointer @p dumpdata - * as a parameter as well as a string with new text to be appended. - * - * @since 1.0.0 - */ - EAPI int eet_data_dump(Eet_File *ef, const char *name, void (*dumpfunc) (void *data, const char *str), void *dumpdata); - - /** - * Take an ascii encoding from eet_data_dump() and re-encode in binary. - * @param ef A valid eet file handle. - * @param name Name of the entry. eg: "/base/file_i_want". - * @param text The pointer to the string data to parse and encode. - * @param textlen The size of the string in bytes (not including 0 byte terminator). - * @param compress Compression flags (1 == compress, 0 = don't compress). - * @return 1 on success, 0 on failure - * - * This function will parse the string pointed to by @p text, encode it the same - * way eet_data_descriptor_encode() takes an in-memory data struct and encodes into a - * binary blob. - * - * The data (optionally compressed) will be in ram, pending a flush to - * disk (it will stay in ram till the eet file handle is closed though). - * - * @since 1.0.0 - */ - EAPI int eet_data_undump(Eet_File *ef, const char *name, const char *text, int textlen, int compress); - - /** - * Decode a data structure from an arbitary location in memory. - * @param edd The data descriptor to use when decoding. - * @param data_in The pointer to the data to decode into a struct. - * @param size_in The size of the data pointed to in bytes. - * @return NULL on failure, or a valid decoded struct pointer on success. - * - * This function will decode a data structure that has been encoded using - * eet_data_descriptor_encode(), and return a data structure with all its - * elements filled out, if successful, or NULL on failure. - * - * The data to be decoded is stored at the memory pointed to by @p data_in, - * and is described by the descriptor pointed to by @p edd. The data size is - * passed in as the value to @p size_in, ande must be greater than 0 to - * succeed. - * - * This function is useful for decoding data structures delivered to the - * application by means other than an eet file, such as an IPC or socket - * connection, raw files, shared memory etc. - * - * Please see eet_data_read() for more information. - * - * @since 1.0.0 - */ - EAPI void *eet_data_descriptor_decode(Eet_Data_Descriptor *edd, const void *data_in, int size_in); - - /** - * Encode a dsata struct to memory and return that encoded data. - * @param edd The data descriptor to use when encoding. - * @param data_in The pointer to the struct to encode into data. - * @param size_ret A pointer to the an int to be filled with the decoded size. - * @return NULL on failure, or a valid encoded data chunk on success. - * - * This function takes a data structutre in memory and encodes it into a - * serialised chunk of data that can be decoded again by - * eet_data_descriptor_decode(). This is useful for being able to transmit - * data structures across sockets, pipes, IPC or shared file mechanisms, - * without having to worry about memory space, machine type, endianess etc. - * - * The parameter @p edd must point to a valid data descriptor, and - * @p data_in must point to the right data structure to encode. If not, the - * encoding may fail. - * - * On success a non NULL valid pointer is returned and what @p size_ret - * points to is set to the size of this decoded data, in bytes. When the - * encoded data is no longer needed, call free() on it. On failure NULL is - * returned and what @p size_ret points to is set to 0. - * - * Please see eet_data_write() for more information. - * - * @since 1.0.0 - */ - EAPI void *eet_data_descriptor_encode(Eet_Data_Descriptor *edd, const void *data_in, int *size_ret); - - /** - * Add a basic data element to a data descriptor. - * @param edd The data descriptor to add the type to. - * @param struct_type The type of the struct. - * @param name The string name to use to encode/decode this member (must be a constant global and never change). - * @param member The struct member itself to be encoded. - * @param type The type of the member to encode. - * - * This macro is a convenience macro provided to add a member to the data - * descriptor @p edd. The type of the structure is provided as the - * @p struct_type parameter (for example: struct my_struct). The @p name - * parameter defines a string that will be used to uniquely name that - * member of the struct (it is suggested to use the struct member itself). - * The @p member parameter is the actual struct member itself (for -eet_dictionary_string_check * example: values), and @p type is the basic data type of the member which - * must be one of: EET_T_CHAR, EET_T_SHORT, EET_T_INT, EET_T_LONG_LONG, - * EET_T_FLOAT, EET_T_DOUBLE, EET_T_UCHAR, EET_T_USHORT, EET_T_UINT, - * EET_T_ULONG_LONG or EET_T_STRING. - * - * @since 1.0.0 - */ -#define EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct_type, name, member, type) \ - { \ - struct_type ___ett; \ - \ - eet_data_descriptor_element_add(edd, name, type, EET_G_UNKNOWN, \ - (char *)(&(___ett.member)) - (char *)(&(___ett)), \ - 0, /* 0, */NULL, NULL); \ - } - - /** - * Add a sub-element type to a data descriptor - * @param edd The data descriptor to add the type to. - * @param struct_type The type of the struct. - * @param name The string name to use to encode/decode this member (must be a constant global and never change). - * @param member The struct member itself to be encoded. - * @param subtype The type of sub-type struct to add. - * - * This macro lets you easily add a sub-type (a struct that's pointed to - * by this one). All the parameters are the same as for - * EET_DATA_DESCRIPTOR_ADD_BASIC(), with the @p subtype being the exception. - * This must be the data descriptor of the struct that is pointed to by - * this element. - * - * @since 1.0.0 - */ -#define EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct_type, name, member, subtype) \ - { \ - struct_type ___ett; \ - \ - eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_UNKNOWN, \ - (char *)(&(___ett.member)) - (char *)(&(___ett)), \ - 0, /* 0, */NULL, subtype); \ - } - - /** - * Add a linked list type to a data descriptor - * @param edd The data descriptor to add the type to. - * @param struct_type The type of the struct. - * @param name The string name to use to encode/decode this member (must be a constant global and never change). - * @param member The struct member itself to be encoded. - * @param subtype The type of linked list member to add. - * - * This macro lets you easily add a linked list of other data types. All the - * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(), with the - * @p subtype being the exception. This must be the data descriptor of the - * element that is in each member of the linked list to be stored. - * - * @since 1.0.0 - */ -#define EET_DATA_DESCRIPTOR_ADD_LIST(edd, struct_type, name, member, subtype) \ - { \ - struct_type ___ett; \ - \ - eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_LIST, \ - (char *)(&(___ett.member)) - (char *)(&(___ett)), \ - 0, /* 0, */NULL, subtype); \ - } - - /** - * Add a hash type to a data descriptor - * @param edd The data descriptor to add the type to. - * @param struct_type The type of the struct. - * @param name The string name to use to encode/decode this member (must be a constant global and never change). - * @param member The struct member itself to be encoded. - * @param subtype The type of hash member to add. - * - * This macro lets you easily add a hash of other data types. All the - * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(), with the - * @p subtype being the exception. This must be the data descriptor of the - * element that is in each member of the hash to be stored. - * - * @since 1.0.0 - */ -#define EET_DATA_DESCRIPTOR_ADD_HASH(edd, struct_type, name, member, subtype) \ - { \ - struct_type ___ett; \ - \ - eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_HASH, \ - (char *)(&(___ett.member)) - (char *)(&(___ett)), \ - 0, /* 0, */NULL, subtype); \ - } - - /** - * Add a fixed size array type to a data descriptor - * @param edd The data descriptor to add the type to. - * @param struct_type The type of the struct. - * @param name The string name to use to encode/decode this member (must be a constant global and never change). - * @param member The struct member itself to be encoded. - * @param subtype The type of hash member to add. - * - * This macro lets you easily add a fixed size array of other data types. All the - * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(), with the - * @p subtype being the exception. This must be the data descriptor of the - * element that is in each member of the hash to be stored. - * - * @since 1.0.2 - */ -#define EET_DATA_DESCRIPTOR_ADD_ARRAY(edd, struct_type, name, member, subtype) \ - { \ - struct_type ___ett; \ - \ - eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_ARRAY, \ - (char *)(&(___ett.member)) - (char *)(&(___ett)), \ - /* 0, */sizeof(___ett.member)/sizeof(___ett.member[0]), NULL, subtype); \ - } - - /** - * Add a variable size array type to a data descriptor - * @param edd The data descriptor to add the type to. - * @param struct_type The type of the struct. - * @param name The string name to use to encode/decode this member (must be a constant global and never change). - * @param member The struct member itself to be encoded. - * @param subtype The type of hash member to add. - * - * This macro lets you easily add a fixed size array of other data types. All the - * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(), with the - * @p subtype being the exception. This must be the data descriptor of the - * element that is in each member of the hash to be stored. - * - * @since 1.0.2 - */ -#define EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(edd, struct_type, name, member, subtype) \ - { \ - struct_type ___ett; \ - \ - eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_VAR_ARRAY, \ - (char *)(&(___ett.member)) - (char *)(&(___ett)), \ - (char *)(&(___ett.member ## _count)) - (char *)(&(___ett)), /* 0, */NULL, subtype); \ - } +/** + * Clear eet cache + * + * For a faster access to previously accessed data, Eet keeps an internal + * cache of files. These files will be freed automatically only when + * they are unused and the cache gets full, in order based on the last time + * they were used. + * On systems with little memory this may present an unnecessary constraint, + * so eet_clearcache() is available for users to reclaim the memory used by + * files that are no longer needed. Those that were open using + * ::EET_FILE_MODE_WRITE or ::EET_FILE_MODE_READ_WRITE and have modifications, + * will be written down to disk before flushing them from memory. + * + * @since 1.0.0 + * @ingroup Eet_Group + */ +EAPI void +eet_clearcache(void); + +/** + * @defgroup Eet_File_Group Eet File Main Functions + * + * Functions to create, destroy and do basic manipulation of + * #Eet_File handles. + * + * This sections explains how to use the most basic Eet functions, which + * are used to work with eet files, read data from them, store it back in or + * take a look at what entries it contains, without making use of the + * serialization capabilities explained in @ref Eet_Data_Group. + * + * The following example will serve as an introduction to most, if not all, + * of these functions. + * + * If you are only using Eet, this is the only header you need to include. + * @dontinclude eet-file.c + * @skipline Eet.h + * + * Now let's create ourselves an eet file to play with. The following function + * shows step by step how to open a file and write some data in it. + * First, we define our file handler and some other things we'll put in it. + * @line static int + * @skip Eet_File + * @until "; + * @skip eet_open + * + * We open a new file in write mode, and if it fails, we just return, since + * there's not much more we can do about it.. + * @until return + * + * Now, we need to write some data in our file. For now, strings will suffice, + * so let's just dump a bunch of them in there. + * @until } + * + * As you can see, we copied a string into our static buffer, which is a bit + * bigger than the full length of the string, and then told Eet to write it + * into the file, compressed, returning the size of the data written into the + * file. + * This is all to show that Eet treats data as just data. It doesn't matter + * what that data represents (for now), it's all just bytes for it. As running + * the following code will show, we took a string of around 30 bytes and put it + * in a buffer of 1024 bytes, but the returned size won't be any of those. + * @until printf + * + * Next, we copy into our buffer our set of strings, including their null + * terminators and write them into the file. No error checking for the sake + * of brevity. And a call to eet_sync() to make sure all out data is + * properly written down to disk, even though we haven't yet closed the file. + * @until eet_sync + * + * One more write, this time our large array of binary data and... well, I + * couldn't come up with a valid use of the last set of strings we stored, + * so let's take it out from the file with eet_delete(). + * @until eet_delete + * + * Finally, we close the file, saving any changes back to disk and return. + * Notice how, if there's any error closing the file or saving its contents, + * the return value from the function will be a false one, which later on + * will make the program exit with an error code. + * @until return + * + * Moving onto our main function, we will open the same file and read it back. + * Trivial, but it'll show how we can do so in more than one way. We'll skip + * the variable declarations, as they aren't very different from what we've + * seen already. + * + * We start from the beginning by initializing Eet so things in general work. + * Forgetting to do so will result in weird results or crashes when calling + * any eet function, so if you experience something like that, the first thing + * to look at is whether eet_init() is missing. + * Then we call our @p create_eet_file function, described above, to make + * sure we have something to work with. If the function fails it will return + * 0 and we just exit, since nothing from here onwards will work anyway. + * @skip eet_init + * @until return + * + * Let's take a look now at what entries our file has. For this, we use + * eet_list(), which will return a list of strings, each being the name of + * one entry. Since we skipped before, it may be worth noting that @p list + * is declared as a @p char **. + * The @p num parameter will, of course, have the number of entries contained + * in our file. + * If everything's fine, we'll get our list and print it to the screen, and + * once done with it, we free the list. That's just the list, not its contents, + * as they are internal strings used by Eet and trying to free them will surely + * break things. + * @until } + * + * Reading back plain data is simple. Just a call to eet_read() with the file + * to read from, and the name of the entry we are interested in. We get back + * our data and the passed @p size parameter will contain the size of it. If + * the data was stored compressed, it will decompressed first. + * @until } + * + * Another simple read for the set of strings from before, except those were + * deleted, so we should get a NULL return and continue normally. + * @until } + * + * Finally, we'll get our binary data in the same way we got the strings. Once + * again, it makes no difference for Eet what the data is, it's up to us to + * know how to handle it. + * @until { + * + * Now some cheating, we know that this data is an Eet file because, well... + * we just know it. So we are going to open it and take a look at its insides. + * For this, eet_open() won't work, as it needs to have a file on disk to read + * from and all we have is some data in RAM. + * + * So how do we do? One way would be to create a normal file and write down + * our data, then open it with eet_open(). Another, faster and more efficient + * if all we want to do is read the file, is to use eet_memopen_read(). + * @until memopen + * + * As you can see, the size we got from our previous read was put to good use + * this time. Unlike the first one where all we had were strings, the size + * of the data read only serves to demonstrate that we are reading back the + * entire size of our original @p buf variable. + * + * A little peeking to see how many entries the file has and to make an + * example of eet_num_entries() to get that number when we don't care about + * their names. + * @until printf + * + * More cheating follows. Just like we knew this was an Eet file, we also know + * what key to read from, and ontop of that we know that the data in it is not + * compressed. + * Knowing all this allows us to take some shortcuts. + * @until read_direct + * + * That's a direct print of our data, whatever that data is. We don't want + * to worry about having to free it later, so we just used eet_direct_read() + * to tell Eet to gives a pointer to the internal data in the file, without + * duplicating it. Since we said that data was not compressed, we shouldn't + * worry about printing garbage to the screen (and yes, we also know the data + * is yet another string). + * We also don't care about the size of the data as it was stored in the file, + * so we passed NULL as the size parameter. + * One very important note about this, however, is that we don't care about + * the size parameter because the data in the file contains the null + * terminator for the string. So when using Eet to store strings this way, + * it's very important to consider whether you will keep that final null + * byte, or to always get the size read and do the necessary checks and copies. + * It's up to the user and the particular use cases to decide how this will + * be done. + * + * With everything done, close this second file and free the data used to open + * it. And this is important, we can't free that data until we are done with + * the file, as Eet is using it. When opening with eet_memopen_read(), the data + * passed to it must be available for as long as the the file is open. + * @until } + * + * Finally, we close the first file, shutdown all internal resources used by + * Eet and leave our main function, thus terminating our program. + * @until return + * + * You can look at the full code of the example @ref eet-file.c "here". + * @{ + */ + +/** + * @enum _Eet_File_Mode + * Modes that a file can be opened. + */ +typedef enum _Eet_File_Mode +{ + EET_FILE_MODE_INVALID = -1, + EET_FILE_MODE_READ, /**< File is read-only. */ + EET_FILE_MODE_WRITE, /**< File is write-only. */ + EET_FILE_MODE_READ_WRITE /**< File is for both read and write */ +} Eet_File_Mode; /**< Modes that a file can be opened. */ + +/** + * @typedef Eet_File + * Opaque handle that defines an Eet file (or memory). + * + * This handle will be returned by the functions eet_open() and + * eet_memopen_read() and is used by every other function that affects the + * file in any way. When you are done with it, call eet_close() to close it + * and, if the file was open for writing, write down to disk any changes made + * to it. + * + * @see eet_open() + * @see eet_memopen_read() + * @see eet_close() + */ +typedef struct _Eet_File Eet_File; + +/** + * @typedef Eet_Dictionary + * Opaque handle that defines a file-backed (mmaped) dictionary of strings. + */ +typedef struct _Eet_Dictionary Eet_Dictionary; + +/** + * @} + */ + +/** + * Open an eet file on disk, and returns a handle to it. + * @param file The file path to the eet file. eg: @c "/tmp/file.eet". + * @param mode The mode for opening. Either #EET_FILE_MODE_READ, + * #EET_FILE_MODE_WRITE or #EET_FILE_MODE_READ_WRITE. + * @return An opened eet file handle. + * @ingroup Eet_File_Group + * + * This function will open an exiting eet file for reading, and build + * the directory table in memory and return a handle to the file, if it + * exists and can be read, and no memory errors occur on the way, otherwise + * NULL will be returned. + * + * It will also open an eet file for writing. This will, if successful, + * delete the original file and replace it with a new empty file, till + * the eet file handle is closed or flushed. If it cannot be opened for + * writing or a memory error occurs, NULL is returned. + * + * You can also open the file for read/write. If you then write a key that + * does not exist it will be created, if the key exists it will be replaced + * by the new data. + * + * If the same file is opened multiple times, then the same file handle will + * be returned as eet maintains an internal list of all currently open + * files. Note that it considers files opened for read only and those opened + * for read/write and write only as 2 separate sets. Those that do not write + * to the file and those that do. Eet will allow 2 handles to the same file + * if they are in the 2 separate lists/groups. That means opening a file for + * read only looks in the read only set, and returns a handle to that file + * handle and increments its reference count. If you open a file for read/write + * or write only it looks in the write set and returns a handle after + * incrementing the reference count. You need to close an eet file handle + * as many times as it has been opened to maintain correct reference counts. + * Files whose modified timestamp or size do not match those of the existing + * referenced file handles will not be returned and a new handle will be + * returned instead. + * + * @since 1.0.0 + */ +EAPI Eet_File * +eet_open(const char *file, + Eet_File_Mode mode); + +/** + * Open an eet file directly from a memory location. The data is not copied, + * so you must keep it around as long as the eet file is open. There is + * currently no cache for this kind of Eet_File, so it's reopened every time + * you use eet_memopen_read. + * @param data Address of file in memory. + * @param size Size of memory to be read. + * @return A handle to the file. + * + * Files opened this way will always be in read-only mode. + * + * @since 1.1.0 + * @ingroup Eet_File_Group + */ +EAPI Eet_File * +eet_memopen_read(const void *data, + size_t size); + +/** + * Get the mode an Eet_File was opened with. + * @param ef A valid eet file handle. + * @return The mode ef was opened with. + * + * @since 1.0.0 + * @ingroup Eet_File_Group + */ +EAPI Eet_File_Mode +eet_mode_get(Eet_File *ef); + +/** + * Close an eet file handle and flush pending writes. + * @param ef A valid eet file handle. + * @return An eet error identifier. + * + * This function will flush any pending writes to disk if the eet file + * was opened for write, and free all data associated with the file handle + * and file, and close the file. If it was opened for read (or read/write), + * the file handle may still be held open internally for caching purposes. + * To flush speculatively held eet file handles use eet_clearcache(). + * + * If the eet file handle is not valid nothing will be done. + * + * @since 1.0.0 + * @ingroup Eet_File_Group + * + * @see eet_clearcache() + */ +EAPI Eet_Error +eet_close(Eet_File *ef); + +/** + * Sync content of an eet file handle, flushing pending writes. + * @param ef A valid eet file handle. + * @return An eet error identifier. + * + * This function will flush any pending writes to disk. The eet file must + * be opened for write. + * + * If the eet file handle is not valid nothing will be done. + * + * @since 1.2.4 + * @ingroup Eet_File_Group + */ +EAPI Eet_Error +eet_sync(Eet_File *ef); + +/** + * Return a handle to the shared string dictionary of the Eet file + * @param ef A valid eet file handle. + * @return A handle to the dictionary of the file + * + * This function returns a handle to the dictionary of an Eet file whose + * handle is @p ef, if a dictionary exists. NULL is returned otherwise or + * if the file handle is known to be invalid. + * + * @see eet_dictionary_string_check() to know if given string came + * from the dictionary or it was dynamically allocated using + * the #Eet_Data_Descriptor_Class instructions. + * + * @since 1.0.0 + * @ingroup Eet_File_Group + */ +EAPI Eet_Dictionary * +eet_dictionary_get(Eet_File *ef); + +/** + * Check if a given string comes from a given dictionary + * @param ed A valid dictionary handle + * @param string A valid 0 byte terminated C string + * @return 1 if it is in the dictionary, 0 otherwise + * + * This checks the given dictionary to see if the given string is actually + * inside that dictionary (i.e. comes from it) and returns 1 if it does. + * If the dictionary handle is invalid, the string is NULL or the string is + * not in the dictionary, 0 is returned. + * + * @since 1.0.0 + * @ingroup Eet_File_Group + */ +EAPI int +eet_dictionary_string_check(Eet_Dictionary *ed, + const char *string); + +/** + * Return the number of strings inside a dictionary + * @param ed A valid dictionary handle + * @return the number of strings inside a dictionary + * + * @since 1.6.0 + * @ingroup Eet_File_Group + */ +EAPI int +eet_dictionary_count(const Eet_Dictionary *ed); + +/** + * Read a specified entry from an eet file and return data + * @param ef A valid eet file handle opened for reading. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param size_ret Number of bytes read from entry and returned. + * @return The data stored in that entry in the eet file. + * + * This function finds an entry in the eet file that is stored under the + * name specified, and returns that data, decompressed, if successful. + * NULL is returned if the lookup fails or if memory errors are + * encountered. It is the job of the calling program to call free() on + * the returned data. The number of bytes in the returned data chunk are + * placed in size_ret. + * + * If the eet file handle is not valid NULL is returned and size_ret is + * filled with 0. + * + * @see eet_read_cipher() + * + * @since 1.0.0 + * @ingroup Eet_File_Group + */ +EAPI void * +eet_read(Eet_File *ef, + const char *name, + int *size_ret); + +/** + * Read a specified entry from an eet file and return data + * @param ef A valid eet file handle opened for reading. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param size_ret Number of bytes read from entry and returned. + * @return The data stored in that entry in the eet file. + * + * This function finds an entry in the eet file that is stored under the + * name specified, and returns that data if not compressed and successful. + * NULL is returned if the lookup fails or if memory errors are + * encountered or if the data is compressed. The calling program must never + * call free() on the returned data. The number of bytes in the returned + * data chunk are placed in size_ret. + * + * If the eet file handle is not valid NULL is returned and size_ret is + * filled with 0. + * + * @since 1.0.0 + * @ingroup Eet_File_Group + */ +EAPI const void * +eet_read_direct(Eet_File *ef, + const char *name, + int *size_ret); + +/** + * Write a specified entry to an eet file handle + * @param ef A valid eet file handle opened for writing. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param data Pointer to the data to be stored. + * @param size Length in bytes in the data to be stored. + * @param compress Compression flags (1 == compress, 0 = don't compress). + * @return bytes written on successful write, 0 on failure. + * + * This function will write the specified chunk of data to the eet file + * and return greater than 0 on success. 0 will be returned on failure. + * + * The eet file handle must be a valid file handle for an eet file opened + * for writing. If it is not, 0 will be returned and no action will be + * performed. + * + * Name, and data must not be NULL, and size must be > 0. If these + * conditions are not met, 0 will be returned. + * + * The data will be copied (and optionally compressed) in ram, pending + * a flush to disk (it will stay in ram till the eet file handle is + * closed though). + * + * @see eet_write_cipher() + * + * @since 1.0.0 + * @ingroup Eet_File_Group + */ +EAPI int +eet_write(Eet_File *ef, + const char *name, + const void *data, + int size, + int compress); + +/** + * Delete a specified entry from an Eet file being written or re-written + * @param ef A valid eet file handle opened for writing. + * @param name Name of the entry. eg: "/base/file_i_want". + * @return Success or failure of the delete. + * + * This function will delete the specified chunk of data from the eet file + * and return greater than 0 on success. 0 will be returned on failure. + * + * The eet file handle must be a valid file handle for an eet file opened + * for writing. If it is not, 0 will be returned and no action will be + * performed. + * + * Name, must not be NULL, otherwise 0 will be returned. + * + * @since 1.0.0 + * @ingroup Eet_File_Group + */ +EAPI int +eet_delete(Eet_File *ef, + const char *name); + +/** + * Alias a specific section to another one. Destination may exist or not, + * no checks are done. + * @param ef A valid eet file handle opened for writing. + * @param name Name of the new entry. eg: "/base/file_i_want". + * @param destination Actual source of the aliased entry eg: "/base/the_real_stuff_i_want". + * @param compress Compression flags (1 == compress, 0 = don't compress). + * @return EINA_TRUE on success, EINA_FALSE on failure. + * + * Name and Destination must not be NULL, otherwise EINA_FALSE will be returned. + * The equivalent of this would be calling 'ln -s destination name' + * + * @since 1.3.3 + * @ingroup Eet_File_Group + */ +EAPI Eina_Bool +eet_alias(Eet_File *ef, + const char *name, + const char *destination, + int compress); + +/** + * Retrieve the filename of an Eet_File + * @param ef A valid eet file handle opened for writing. + * @return The stringshared file string opened with eet_open(), or NULL on error + * + * @note This function will return NULL for files opened with eet_memopen_read() + * + * @since 1.6 + * @ingroup Eet_File_Group + */ +EAPI const char * +eet_file_get(Eet_File *ef); + +/** + * Retrieve the destination name of an alias + * @param ef A valid eet file handle opened for writing + * @param name Name of the entry. eg: "/base/file_i_want" + * @return Destination of the alias. eg: "/base/the_real_stuff_i_want", NULL on failure + * + * Name must not be NULL, otherwise NULL will be returned. + * + * @since 1.5 + * @ingroup Eet_File_Group + */ +EAPI const char * +eet_alias_get(Eet_File *ef, + const char *name); + +/** + * List all entries in eet file matching shell glob. + * @param ef A valid eet file handle. + * @param glob A shell glob to match against. + * @param count_ret Number of entries found to match. + * @return Pointer to an array of strings. + * + * This function will list all entries in the eet file matching the + * supplied shell glob and return an allocated list of their names, if + * there are any, and if no memory errors occur. + * + * The eet file handle must be valid and glob must not be NULL, or NULL + * will be returned and count_ret will be filled with 0. + * + * The calling program must call free() on the array returned, but NOT + * on the string pointers in the array. They are taken as read-only + * internals from the eet file handle. They are only valid as long as + * the file handle is not closed. When it is closed those pointers in the + * array are now not valid and should not be used. + * + * On success the array returned will have a list of string pointers + * that are the names of the entries that matched, and count_ret will have + * the number of entries in this array placed in it. + * + * Hint: an easy way to list all entries in an eet file is to use a glob + * value of "*". + * + * @since 1.0.0 + * @ingroup Eet_File_Group + */ +EAPI char ** +eet_list(Eet_File *ef, + const char *glob, + int *count_ret); + +/** + * Return the number of entries in the specified eet file. + * @param ef A valid eet file handle. + * @return Number of entries in ef or -1 if the number of entries + * cannot be read due to open mode restrictions. + * + * @since 1.0.0 + * @ingroup Eet_File_Group + */ +EAPI int +eet_num_entries(Eet_File *ef); + +/** + * @defgroup Eet_File_Cipher_Group Eet File Ciphered Main Functions + * + * Most of the @ref Eet_File_Group have alternative versions that + * accounts for ciphers to protect their content. + * + * @see @ref Eet_Cipher_Group + * + * @ingroup Eet_File_Group + */ + +/** + * Read a specified entry from an eet file and return data using a cipher. + * @param ef A valid eet file handle opened for reading. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param size_ret Number of bytes read from entry and returned. + * @param cipher_key The key to use as cipher. + * @return The data stored in that entry in the eet file. + * + * This function finds an entry in the eet file that is stored under the + * name specified, and returns that data, decompressed, if successful. + * NULL is returned if the lookup fails or if memory errors are + * encountered. It is the job of the calling program to call free() on + * the returned data. The number of bytes in the returned data chunk are + * placed in size_ret. + * + * If the eet file handle is not valid NULL is returned and size_ret is + * filled with 0. + * + * @see eet_read() + * + * @since 1.0.0 + * @ingroup Eet_File_Cipher_Group + */ +EAPI void * +eet_read_cipher(Eet_File *ef, + const char *name, + int *size_ret, + const char *cipher_key); + +/** + * Write a specified entry to an eet file handle using a cipher. + * @param ef A valid eet file handle opened for writing. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param data Pointer to the data to be stored. + * @param size Length in bytes in the data to be stored. + * @param compress Compression flags (1 == compress, 0 = don't compress). + * @param cipher_key The key to use as cipher. + * @return bytes written on successful write, 0 on failure. + * + * This function will write the specified chunk of data to the eet file + * and return greater than 0 on success. 0 will be returned on failure. + * + * The eet file handle must be a valid file handle for an eet file opened + * for writing. If it is not, 0 will be returned and no action will be + * performed. + * + * Name, and data must not be NULL, and size must be > 0. If these + * conditions are not met, 0 will be returned. + * + * The data will be copied (and optionally compressed) in ram, pending + * a flush to disk (it will stay in ram till the eet file handle is + * closed though). + * + * @see eet_write() + * + * @since 1.0.0 + * @ingroup Eet_File_Cipher_Group + */ +EAPI int +eet_write_cipher(Eet_File *ef, + const char *name, + const void *data, + int size, + int compress, + const char *cipher_key); + +/** + * @defgroup Eet_File_Image_Group Image Store and Load + * + * Eet efficiently stores and loads images, including alpha + * channels and lossy compressions. + * + * Eet can handle both lossy compression with different levels of quality and + * non-lossy compression with different compression levels. It's also possible, + * given an image data, to only read its header to get the image information + * without decoding the entire content for it. + * + * The encode family of functions will take an image raw buffer and its + * parameters and compress it in memory, returning the new buffer. + * Likewise, the decode functions will read from the given location in memory + * and return the uncompressed image. + * + * The read and write functions will, respectively, encode and decode to or + * from an Eet file, under the specified key. + * + * These functions are fairly low level and the same functionality can be + * achieved using Evas and Edje, making it much easier to work with images + * as well as not needing to worry about things like scaling them. + */ + +/** + * Read just the header data for an image and dont decode the pixels. + * @param ef A valid eet file handle opened for reading. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param w A pointer to the unsigned int to hold the width in pixels. + * @param h A pointer to the unsigned int to hold the height in pixels. + * @param alpha A pointer to the int to hold the alpha flag. + * @param compress A pointer to the int to hold the compression amount. + * @param quality A pointer to the int to hold the quality amount. + * @param lossy A pointer to the int to hold the lossiness flag. + * @return 1 on successful decode, 0 otherwise + * + * Reads and decodes the image header data stored under the given key and + * Eet file. + * + * The information decoded is placed in each of the parameters, which must be + * provided. The width and height, measured in pixels, will be stored under + * the variables pointed by @p w and @p h, respectively. If the read or + * decode of the header fails, this values will be 0. The @p alpha parameter + * will be 1 or 0, denoting if the alpha channel of the image is used or not. + * If the image was losslessly compressed, the @p compress parameter will hold + * the compression amount used, ranging from 0 to 9 and @p lossy will be 0. + * In the case of lossy compression, @p lossy will be 1, and the compression + * quality will be placed under @p quality, with a value ranging from 0 to 100. + * + * @see eet_data_image_header_decode() + * @see eet_data_image_header_read_cipher() + * + * @since 1.0.0 + * @ingroup Eet_File_Image_Group + */ +EAPI int +eet_data_image_header_read(Eet_File *ef, + const char *name, + unsigned int *w, + unsigned int *h, + int *alpha, + int *compress, + int *quality, + int *lossy); + +/** + * Read image data from the named key in the eet file. + * @param ef A valid eet file handle opened for reading. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param w A pointer to the unsigned int to hold the width in pixels. + * @param h A pointer to the unsigned int to hold the height in pixels. + * @param alpha A pointer to the int to hold the alpha flag. + * @param compress A pointer to the int to hold the compression amount. + * @param quality A pointer to the int to hold the quality amount. + * @param lossy A pointer to the int to hold the lossiness flag. + * @return The image pixel data decoded + * + * Reads and decodes the image stored in the given Eet file under the named + * key. + * + * The returned pixel data is a linear array of pixels starting from the + * top-left of the image, scanning row by row from left to right. Each pile + * is a 32bit value, with the high byte being the alpha channel, the next being + * red, then green, and the low byte being blue. + * + * The rest of the parameters are the same as in eet_data_image_header_read(). + * + * On success the function returns a pointer to the image data decoded. The + * calling application is responsible for calling free() on the image data + * when it is done with it. On failure NULL is returned and the parameter + * values may not contain any sensible data. + * + * @see eet_data_image_header_read() + * @see eet_data_image_decode() + * @see eet_data_image_read_cipher() + * @see eet_data_image_read_to_surface() + * + * @since 1.0.0 + * @ingroup Eet_File_Image_Group + */ +EAPI void * +eet_data_image_read(Eet_File *ef, + const char *name, + unsigned int *w, + unsigned int *h, + int *alpha, + int *compress, + int *quality, + int *lossy); + +/** + * Read image data from the named key in the eet file and store it in the given buffer. + * @param ef A valid eet file handle opened for reading. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param src_x The starting x coordinate from where to dump the stream. + * @param src_y The starting y coordinate from where to dump the stream. + * @param d A pointer to the pixel surface. + * @param w The expected width in pixels of the pixel surface to decode. + * @param h The expected height in pixels of the pixel surface to decode. + * @param row_stride The length of a pixels line in the destination surface. + * @param alpha A pointer to the int to hold the alpha flag. + * @param compress A pointer to the int to hold the compression amount. + * @param quality A pointer to the int to hold the quality amount. + * @param lossy A pointer to the int to hold the lossiness flag. + * @return 1 on success, 0 otherwise. + * + * Reads and decodes the image stored in the given Eet file, placing the + * resulting pixel data in the buffer pointed by the user. + * + * Like eet_data_image_read(), it takes the image data stored under the + * @p name key in the @p ef file, but instead of returning a new buffer with + * the pixel data, it places the result in the buffer pointed by @p d, which + * must be provided by the user and of sufficient size to hold the requested + * portion of the image. + * + * The @p src_x and @p src_y parameters indicate the top-left corner of the + * section of the image to decode. These have to be higher or equal than 0 and + * less than the respective total width and height of the image. The width + * and height of the section of the image to decode are given in @p w and @p h + * and also can't be higher than the total width and height of the image. + * + * The @p row_stride parameter indicates the length in bytes of each line in + * the destination buffer and it has to be at least @p w * 4. + * + * All the other parameters are the same as in eet_data_image_read(). + * + * On success the function returns 1, and 0 on failure. On failure the + * parameter values may not contain any sensible data. + * + * @see eet_data_image_read() + * @see eet_data_image_decode() + * @see eet_data_image_decode_to_surface() + * @see eet_data_image_read_to_surface_cipher() + * + * @since 1.0.2 + * @ingroup Eet_File_Image_Group + */ +EAPI int +eet_data_image_read_to_surface(Eet_File *ef, + const char *name, + unsigned int src_x, + unsigned int src_y, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride, + int *alpha, + int *compress, + int *quality, + int *lossy); + +/** + * Write image data to the named key in an eet file. + * @param ef A valid eet file handle opened for writing. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param data A pointer to the image pixel data. + * @param w The width of the image in pixels. + * @param h The height of the image in pixels. + * @param alpha The alpha channel flag. + * @param compress The compression amount. + * @param quality The quality encoding amount. + * @param lossy The lossiness flag. + * @return Success if the data was encoded and written or not. + * + * This function takes image pixel data and encodes it in an eet file + * stored under the supplied name key, and returns how many bytes were + * actually written to encode the image data. + * + * The data expected is the same format as returned by eet_data_image_read. + * If this is not the case weird things may happen. Width and height must + * be between 1 and 8000 pixels. The alpha flags can be 0 or 1 (0 meaning + * the alpha values are not useful and 1 meaning they are). Compress can + * be from 0 to 9 (0 meaning no compression, 9 meaning full compression). + * This is only used if the image is not lossily encoded. Quality is used on + * lossy compression and should be a value from 0 to 100. The lossy flag + * can be 0 or 1. 0 means encode losslessly and 1 means to encode with + * image quality loss (but then have a much smaller encoding). + * + * On success this function returns the number of bytes that were required + * to encode the image data, or on failure it returns 0. + * + * @see eet_data_image_read() + * @see eet_data_image_encode() + * @see eet_data_image_write_cipher() + * + * @since 1.0.0 + * @ingroup Eet_File_Image_Group + */ +EAPI int +eet_data_image_write(Eet_File *ef, + const char *name, + const void *data, + unsigned int w, + unsigned int h, + int alpha, + int compress, + int quality, + int lossy); + +/** + * Decode Image data header only to get information. + * @param data The encoded pixel data. + * @param size The size, in bytes, of the encoded pixel data. + * @param w A pointer to the unsigned int to hold the width in pixels. + * @param h A pointer to the unsigned int to hold the height in pixels. + * @param alpha A pointer to the int to hold the alpha flag. + * @param compress A pointer to the int to hold the compression amount. + * @param quality A pointer to the int to hold the quality amount. + * @param lossy A pointer to the int to hold the lossiness flag. + * @return 1 on success, 0 on failure. + * + * This function works exactly like eet_data_image_header_read(), but instead + * of reading from an Eet file, it takes the buffer of size @p size pointed + * by @p data, which must be a valid Eet encoded image. + * + * On success the function returns 1 indicating the header was read and + * decoded properly, or 0 on failure. + * + * @see eet_data_image_header_read() + * @see eet_data_image_header_decode_cipher() + * + * @since 1.0.0 + * @ingroup Eet_File_Image_Group + */ +EAPI int +eet_data_image_header_decode(const void *data, + int size, + unsigned int *w, + unsigned int *h, + int *alpha, + int *compress, + int *quality, + int *lossy); + +/** + * Decode Image data into pixel data. + * @param data The encoded pixel data. + * @param size The size, in bytes, of the encoded pixel data. + * @param w A pointer to the unsigned int to hold the width in pixels. + * @param h A pointer to the unsigned int to hold the height in pixels. + * @param alpha A pointer to the int to hold the alpha flag. + * @param compress A pointer to the int to hold the compression amount. + * @param quality A pointer to the int to hold the quality amount. + * @param lossy A pointer to the int to hold the lossiness flag. + * @return The image pixel data decoded + * + * This function takes encoded pixel data and decodes it into raw RGBA + * pixels on success. + * + * It works exactly like eet_data_image_read(), but it takes the encoded + * data in the @p data buffer of size @p size, instead of reading from a file. + * All the others parameters are also the same. + * + * On success the function returns a pointer to the image data decoded. The + * calling application is responsible for calling free() on the image data + * when it is done with it. On failure NULL is returned and the parameter + * values may not contain any sensible data. + * + * @see eet_data_image_read() + * @see eet_data_image_decode_cipher() + * + * @since 1.0.0 + * @ingroup Eet_File_Image_Group + */ +EAPI void * +eet_data_image_decode(const void *data, + int size, + unsigned int *w, + unsigned int *h, + int *alpha, + int *compress, + int *quality, + int *lossy); + +/** + * Decode Image data into pixel data and stores in the given buffer. + * @param data The encoded pixel data. + * @param size The size, in bytes, of the encoded pixel data. + * @param src_x The starting x coordinate from where to dump the stream. + * @param src_y The starting y coordinate from where to dump the stream. + * @param d A pointer to the pixel surface. + * @param w The expected width in pixels of the pixel surface to decode. + * @param h The expected height in pixels of the pixel surface to decode. + * @param row_stride The length of a pixels line in the destination surface. + * @param alpha A pointer to the int to hold the alpha flag. + * @param compress A pointer to the int to hold the compression amount. + * @param quality A pointer to the int to hold the quality amount. + * @param lossy A pointer to the int to hold the lossiness flag. + * @return 1 on success, 0 otherwise. + * + * Like eet_data_image_read_to_surface(), but reading the given @p data buffer + * instead of a file. + * + * On success the function returns 1, and 0 on failure. On failure the + * parameter values may not contain any sensible data. + * + * @see eet_data_image_read_to_surface() + * @see eet_data_image_decode_to_surface_cipher() + * + * @since 1.0.2 + * @ingroup Eet_File_Image_Group + */ +EAPI int +eet_data_image_decode_to_surface(const void *data, + int size, + unsigned int src_x, + unsigned int src_y, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride, + int *alpha, + int *compress, + int *quality, + int *lossy); + +/** + * Encode image data for storage or transmission. + * @param data A pointer to the image pixel data. + * @param size_ret A pointer to an int to hold the size of the returned data. + * @param w The width of the image in pixels. + * @param h The height of the image in pixels. + * @param alpha The alpha channel flag. + * @param compress The compression amount. + * @param quality The quality encoding amount. + * @param lossy The lossiness flag. + * @return The encoded image data. + * + * This function stakes image pixel data and encodes it with compression and + * possible loss of quality (as a trade off for size) for storage or + * transmission to another system. + * + * It works like eet_data_image_write(), but instead of writing the encoded + * image into an Eet file, it allocates a new buffer of the size required and + * returns the encoded data in it. + * + * On success this function returns a pointer to the encoded data that you + * can free with free() when no longer needed. + * + * @see eet_data_image_write() + * @see eet_data_image_read() + * @see eet_data_image_encode_cipher() + * + * @since 1.0.0 + * @ingroup Eet_File_Image_Group + */ +EAPI void * +eet_data_image_encode(const void *data, + int *size_ret, + unsigned int w, + unsigned int h, + int alpha, + int compress, + int quality, + int lossy); + +/** + * @defgroup Eet_File_Image_Cipher_Group Image Store and Load using a Cipher + * + * Most of the @ref Eet_File_Image_Group have alternative versions + * that accounts for ciphers to protect their content. + * + * @see @ref Eet_Cipher_Group + * + * @ingroup Eet_File_Image_Group + */ + +/** + * Read just the header data for an image and dont decode the pixels using a cipher. + * @param ef A valid eet file handle opened for reading. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param cipher_key The key to use as cipher. + * @param w A pointer to the unsigned int to hold the width in pixels. + * @param h A pointer to the unsigned int to hold the height in pixels. + * @param alpha A pointer to the int to hold the alpha flag. + * @param compress A pointer to the int to hold the compression amount. + * @param quality A pointer to the int to hold the quality amount. + * @param lossy A pointer to the int to hold the lossiness flag. + * @return 1 on successful decode, 0 otherwise + * + * This function reads an image from an eet file stored under the named + * key in the eet file and return a pointer to the decompressed pixel data. + * + * The other parameters of the image (width, height etc.) are placed into + * the values pointed to (they must be supplied). The pixel data is a linear + * array of pixels starting from the top-left of the image scanning row by + * row from left to right. Each pixel is a 32bit value, with the high byte + * being the alpha channel, the next being red, then green, and the low byte + * being blue. The width and height are measured in pixels and will be + * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes + * that the alpha channel is not used. 1 denotes that it is significant. + * Compress is filled with the compression value/amount the image was + * stored with. The quality value is filled with the quality encoding of + * the image file (0 - 100). The lossy flags is either 0 or 1 as to if + * the image was encoded lossily or not. + * + * On success the function returns 1 indicating the header was read and + * decoded properly, or 0 on failure. + * + * @see eet_data_image_header_read() + * + * @since 1.0.0 + * @ingroup Eet_File_Image_Cipher_Group + */ +EAPI int +eet_data_image_header_read_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + unsigned int *w, + unsigned int *h, + int *alpha, + int *compress, + int *quality, + int *lossy); + +/** + * Read image data from the named key in the eet file using a cipher. + * @param ef A valid eet file handle opened for reading. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param cipher_key The key to use as cipher. + * @param w A pointer to the unsigned int to hold the width in pixels. + * @param h A pointer to the unsigned int to hold the height in pixels. + * @param alpha A pointer to the int to hold the alpha flag. + * @param compress A pointer to the int to hold the compression amount. + * @param quality A pointer to the int to hold the quality amount. + * @param lossy A pointer to the int to hold the lossiness flag. + * @return The image pixel data decoded + * + * This function reads an image from an eet file stored under the named + * key in the eet file and return a pointer to the decompressed pixel data. + * + * The other parameters of the image (width, height etc.) are placed into + * the values pointed to (they must be supplied). The pixel data is a linear + * array of pixels starting from the top-left of the image scanning row by + * row from left to right. Each pixel is a 32bit value, with the high byte + * being the alpha channel, the next being red, then green, and the low byte + * being blue. The width and height are measured in pixels and will be + * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes + * that the alpha channel is not used. 1 denotes that it is significant. + * Compress is filled with the compression value/amount the image was + * stored with. The quality value is filled with the quality encoding of + * the image file (0 - 100). The lossy flags is either 0 or 1 as to if + * the image was encoded lossily or not. + * + * On success the function returns a pointer to the image data decoded. The + * calling application is responsible for calling free() on the image data + * when it is done with it. On failure NULL is returned and the parameter + * values may not contain any sensible data. + * + * @see eet_data_image_read() + * + * @since 1.0.0 + * @ingroup Eet_File_Image_Cipher_Group + */ +EAPI void * +eet_data_image_read_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + unsigned int *w, + unsigned int *h, + int *alpha, + int *compress, + int *quality, + int *lossy); + +/** + * Read image data from the named key in the eet file using a cipher. + * @param ef A valid eet file handle opened for reading. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param cipher_key The key to use as cipher. + * @param src_x The starting x coordinate from where to dump the stream. + * @param src_y The starting y coordinate from where to dump the stream. + * @param d A pointer to the pixel surface. + * @param w The expected width in pixels of the pixel surface to decode. + * @param h The expected height in pixels of the pixel surface to decode. + * @param row_stride The length of a pixels line in the destination surface. + * @param alpha A pointer to the int to hold the alpha flag. + * @param compress A pointer to the int to hold the compression amount. + * @param quality A pointer to the int to hold the quality amount. + * @param lossy A pointer to the int to hold the lossiness flag. + * @return 1 on success, 0 otherwise. + * + * This function reads an image from an eet file stored under the named + * key in the eet file and return a pointer to the decompressed pixel data. + * + * The other parameters of the image (width, height etc.) are placed into + * the values pointed to (they must be supplied). The pixel data is a linear + * array of pixels starting from the top-left of the image scanning row by + * row from left to right. Each pixel is a 32bit value, with the high byte + * being the alpha channel, the next being red, then green, and the low byte + * being blue. The width and height are measured in pixels and will be + * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes + * that the alpha channel is not used. 1 denotes that it is significant. + * Compress is filled with the compression value/amount the image was + * stored with. The quality value is filled with the quality encoding of + * the image file (0 - 100). The lossy flags is either 0 or 1 as to if + * the image was encoded lossily or not. + * + * On success the function returns 1, and 0 on failure. On failure the + * parameter values may not contain any sensible data. + * + * @see eet_data_image_read_to_surface() + * + * @since 1.0.2 + * @ingroup Eet_File_Image_Cipher_Group + */ +EAPI int +eet_data_image_read_to_surface_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + unsigned int src_x, + unsigned int src_y, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride, + int *alpha, + int *compress, + int *quality, + int *lossy); + +/** + * Write image data to the named key in an eet file using a cipher. + * @param ef A valid eet file handle opened for writing. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param cipher_key The key to use as cipher. + * @param data A pointer to the image pixel data. + * @param w The width of the image in pixels. + * @param h The height of the image in pixels. + * @param alpha The alpha channel flag. + * @param compress The compression amount. + * @param quality The quality encoding amount. + * @param lossy The lossiness flag. + * @return Success if the data was encoded and written or not. + * + * This function takes image pixel data and encodes it in an eet file + * stored under the supplied name key, and returns how many bytes were + * actually written to encode the image data. + * + * The data expected is the same format as returned by eet_data_image_read. + * If this is not the case weird things may happen. Width and height must + * be between 1 and 8000 pixels. The alpha flags can be 0 or 1 (0 meaning + * the alpha values are not useful and 1 meaning they are). Compress can + * be from 0 to 9 (0 meaning no compression, 9 meaning full compression). + * This is only used if the image is not lossily encoded. Quality is used on + * lossy compression and should be a value from 0 to 100. The lossy flag + * can be 0 or 1. 0 means encode losslessly and 1 means to encode with + * image quality loss (but then have a much smaller encoding). + * + * On success this function returns the number of bytes that were required + * to encode the image data, or on failure it returns 0. + * + * @see eet_data_image_write() + * + * @since 1.0.0 + * @ingroup Eet_File_Image_Cipher_Group + */ +EAPI int +eet_data_image_write_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + const void *data, + unsigned int w, + unsigned int h, + int alpha, + int compress, + int quality, + int lossy); + +/** + * Decode Image data header only to get information using a cipher. + * @param data The encoded pixel data. + * @param cipher_key The key to use as cipher. + * @param size The size, in bytes, of the encoded pixel data. + * @param w A pointer to the unsigned int to hold the width in pixels. + * @param h A pointer to the unsigned int to hold the height in pixels. + * @param alpha A pointer to the int to hold the alpha flag. + * @param compress A pointer to the int to hold the compression amount. + * @param quality A pointer to the int to hold the quality amount. + * @param lossy A pointer to the int to hold the lossiness flag. + * @return 1 on success, 0 on failure. + * + * This function takes encoded pixel data and decodes it into raw RGBA + * pixels on success. + * + * The other parameters of the image (width, height etc.) are placed into + * the values pointed to (they must be supplied). The pixel data is a linear + * array of pixels starting from the top-left of the image scanning row by + * row from left to right. Each pixel is a 32bit value, with the high byte + * being the alpha channel, the next being red, then green, and the low byte + * being blue. The width and height are measured in pixels and will be + * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes + * that the alpha channel is not used. 1 denotes that it is significant. + * Compress is filled with the compression value/amount the image was + * stored with. The quality value is filled with the quality encoding of + * the image file (0 - 100). The lossy flags is either 0 or 1 as to if + * the image was encoded lossily or not. + * + * On success the function returns 1 indicating the header was read and + * decoded properly, or 0 on failure. + * + * @see eet_data_image_header_decode() + * + * @since 1.0.0 + * @ingroup Eet_File_Image_Cipher_Group + */ +EAPI int +eet_data_image_header_decode_cipher(const void *data, + const char *cipher_key, + int size, + unsigned int *w, + unsigned int *h, + int *alpha, + int *compress, + int *quality, + int *lossy); + +/** + * Decode Image data into pixel data using a cipher. + * @param data The encoded pixel data. + * @param cipher_key The key to use as cipher. + * @param size The size, in bytes, of the encoded pixel data. + * @param w A pointer to the unsigned int to hold the width in pixels. + * @param h A pointer to the unsigned int to hold the height in pixels. + * @param alpha A pointer to the int to hold the alpha flag. + * @param compress A pointer to the int to hold the compression amount. + * @param quality A pointer to the int to hold the quality amount. + * @param lossy A pointer to the int to hold the lossiness flag. + * @return The image pixel data decoded + * + * This function takes encoded pixel data and decodes it into raw RGBA + * pixels on success. + * + * The other parameters of the image (width, height etc.) are placed into + * the values pointed to (they must be supplied). The pixel data is a linear + * array of pixels starting from the top-left of the image scanning row by + * row from left to right. Each pixel is a 32bit value, with the high byte + * being the alpha channel, the next being red, then green, and the low byte + * being blue. The width and height are measured in pixels and will be + * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes + * that the alpha channel is not used. 1 denotes that it is significant. + * Compress is filled with the compression value/amount the image was + * stored with. The quality value is filled with the quality encoding of + * the image file (0 - 100). The lossy flags is either 0 or 1 as to if + * the image was encoded lossily or not. + * + * On success the function returns a pointer to the image data decoded. The + * calling application is responsible for calling free() on the image data + * when it is done with it. On failure NULL is returned and the parameter + * values may not contain any sensible data. + * + * @see eet_data_image_decode() + * + * @since 1.0.0 + * @ingroup Eet_File_Image_Cipher_Group + */ +EAPI void * +eet_data_image_decode_cipher(const void *data, + const char *cipher_key, + int size, + unsigned int *w, + unsigned int *h, + int *alpha, + int *compress, + int *quality, + int *lossy); + +/** + * Decode Image data into pixel data using a cipher. + * @param data The encoded pixel data. + * @param cipher_key The key to use as cipher. + * @param size The size, in bytes, of the encoded pixel data. + * @param src_x The starting x coordinate from where to dump the stream. + * @param src_y The starting y coordinate from where to dump the stream. + * @param d A pointer to the pixel surface. + * @param w The expected width in pixels of the pixel surface to decode. + * @param h The expected height in pixels of the pixel surface to decode. + * @param row_stride The length of a pixels line in the destination surface. + * @param alpha A pointer to the int to hold the alpha flag. + * @param compress A pointer to the int to hold the compression amount. + * @param quality A pointer to the int to hold the quality amount. + * @param lossy A pointer to the int to hold the lossiness flag. + * @return 1 on success, 0 otherwise. + * + * This function takes encoded pixel data and decodes it into raw RGBA + * pixels on success. + * + * The other parameters of the image (alpha, compress etc.) are placed into + * the values pointed to (they must be supplied). The pixel data is a linear + * array of pixels starting from the top-left of the image scanning row by + * row from left to right. Each pixel is a 32bit value, with the high byte + * being the alpha channel, the next being red, then green, and the low byte + * being blue. The width and height are measured in pixels and will be + * greater than 0 when returned. The alpha flag is either 0 or 1. 0 denotes + * that the alpha channel is not used. 1 denotes that it is significant. + * Compress is filled with the compression value/amount the image was + * stored with. The quality value is filled with the quality encoding of + * the image file (0 - 100). The lossy flags is either 0 or 1 as to if + * the image was encoded lossily or not. + * + * On success the function returns 1, and 0 on failure. On failure the + * parameter values may not contain any sensible data. + * + * @see eet_data_image_decode_to_surface() + * + * @since 1.0.2 + * @ingroup Eet_File_Image_Cipher_Group + */ +EAPI int +eet_data_image_decode_to_surface_cipher(const void *data, + const char *cipher_key, + int size, + unsigned int src_x, + unsigned int src_y, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride, + int *alpha, + int *compress, + int *quality, + int *lossy); + +/** + * Encode image data for storage or transmission using a cipher. + * @param data A pointer to the image pixel data. + * @param cipher_key The key to use as cipher. + * @param size_ret A pointer to an int to hold the size of the returned data. + * @param w The width of the image in pixels. + * @param h The height of the image in pixels. + * @param alpha The alpha channel flag. + * @param compress The compression amount. + * @param quality The quality encoding amount. + * @param lossy The lossiness flag. + * @return The encoded image data. + * + * This function stakes image pixel data and encodes it with compression and + * possible loss of quality (as a trade off for size) for storage or + * transmission to another system. + * + * The data expected is the same format as returned by eet_data_image_read. + * If this is not the case weird things may happen. Width and height must + * be between 1 and 8000 pixels. The alpha flags can be 0 or 1 (0 meaning + * the alpha values are not useful and 1 meaning they are). Compress can + * be from 0 to 9 (0 meaning no compression, 9 meaning full compression). + * This is only used if the image is not lossily encoded. Quality is used on + * lossy compression and should be a value from 0 to 100. The lossy flag + * can be 0 or 1. 0 means encode losslessly and 1 means to encode with + * image quality loss (but then have a much smaller encoding). + * + * On success this function returns a pointer to the encoded data that you + * can free with free() when no longer needed. + * + * @see eet_data_image_encode() + * + * @since 1.0.0 + * @ingroup Eet_File_Image_Cipher_Group + */ +EAPI void * +eet_data_image_encode_cipher(const void *data, + const char *cipher_key, + unsigned int w, + unsigned int h, + int alpha, + int compress, + int quality, + int lossy, + int *size_ret); + +/** + * @defgroup Eet_Cipher_Group Cipher, Identity and Protection Mechanisms + * + * Eet allows one to protect entries of an #Eet_File + * individually. This may be used to ensure data was not tampered or + * that third party does not read your data. + * + * @see @ref Eet_File_Cipher_Group + * @see @ref Eet_File_Image_Cipher_Group + * + * @{ + */ + +/** + * @typedef Eet_Key + * Opaque handle that defines an identity (also known as key) + * in Eet's cipher system. + */ +typedef struct _Eet_Key Eet_Key; + +/** + * @} + */ + +/** + * Callback used to request if needed the password of a private key. + * + * @param buffer the buffer where to store the password. + * @param size the maximum password size (size of buffer, including '@\0'). + * @param rwflag if the buffer is also readable or just writable. + * @param data currently unused, may contain some context in future. + * @return 1 on success and password was set to @p buffer, 0 on failure. + * + * @since 1.2.0 + * @ingroup Eet_Cipher_Group + */ +typedef int (*Eet_Key_Password_Callback)(char *buffer, int size, int rwflag, void *data); + +/** + * Create an Eet_Key needed for signing an eet file. + * + * The certificate should provide the public that match the private key. + * No verification is done to ensure that. + * + * @param certificate_file The file where to find the certificate. + * @param private_key_file The file that contains the private key. + * @param cb Function to callback if password is required to unlock + * private key. + * @return A key handle to use, or @c NULL on failure. + * + * @see eet_identity_close() + * + * @warning You need to compile signature support in EET. + * @since 1.2.0 + * @ingroup Eet_Cipher_Group + */ +EAPI Eet_Key * +eet_identity_open(const char *certificate_file, + const char *private_key_file, + Eet_Key_Password_Callback cb); + +/** + * Close and release all resource used by an Eet_Key. An + * reference counter prevent it from being freed until all file + * using it are also closed. + * + * @param key the key handle to close and free resources. + * + * @since 1.2.0 + * @ingroup Eet_Cipher_Group + */ +EAPI void +eet_identity_close(Eet_Key *key); + +/** + * Set a key to sign a file + * + * @param ef the file to set the identity. + * @param key the key handle to set as identity. + * @return #EET_ERROR_BAD_OBJECT if @p ef is invalid or + * #EET_ERROR_NONE on success. + * + * @since 1.2.0 + * @ingroup Eet_Cipher_Group + */ +EAPI Eet_Error +eet_identity_set(Eet_File *ef, + Eet_Key *key); + +/** + * Display both private and public key of an Eet_Key. + * + * @param key the handle to print. + * @param out where to print. + * + * @warning You need to compile signature support in EET. + * @since 1.2.0 + * @ingroup Eet_Cipher_Group + */ +EAPI void +eet_identity_print(Eet_Key *key, + FILE *out); + +/** + * Get the x509 der certificate associated with an Eet_File. Will return NULL + * if the file is not signed. + * + * @param ef The file handle to query. + * @param der_length The length of returned data, may be @c NULL. + * @return the x509 certificate or @c NULL on error. + * + * @since 1.2.0 + * @ingroup Eet_Cipher_Group + */ +EAPI const void * +eet_identity_x509(Eet_File *ef, + int *der_length); + +/** + * Get the raw signature associated with an Eet_File. Will return NULL + * if the file is not signed. + * + * @param ef The file handle to query. + * @param signature_length The length of returned data, may be @c NULL. + * @return the raw signature or @c NULL on error. + * + * @ingroup Eet_Cipher_Group + */ +EAPI const void * +eet_identity_signature(Eet_File *ef, + int *signature_length); + +/** + * Get the SHA1 associated with a file. Could be the one used to + * sign the data or if the data where not signed, it will be the + * SHA1 of the file. + * + * @param ef The file handle to query. + * @param sha1_length The length of returned data, may be @c NULL. + * @return the associated SHA1 or @c NULL on error. + * + * @since 1.2.0 + * @ingroup Eet_Cipher_Group + */ +EAPI const void * +eet_identity_sha1(Eet_File *ef, + int *sha1_length); + +/** + * Display the x509 der certificate to out. + * + * @param certificate the x509 certificate to print + * @param der_length The length the certificate. + * @param out where to print. + * + * @warning You need to compile signature support in EET. + * @since 1.2.0 + * @ingroup Eet_Cipher_Group + */ +EAPI void +eet_identity_certificate_print(const unsigned char *certificate, + int der_length, + FILE *out); + +/** + * @defgroup Eet_Data_Group Eet Data Serialization + * + * Convenience functions to serialize and parse complex data + * structures to binary blobs. + * + * While Eet core just handles binary blobs, it is often required + * to save some structured data of different types, such as + * strings, integers, lists, hashes and so on. + * + * Eet can serialize and then parse data types given some + * construction instructions. These are defined in two levels: + * + * - #Eet_Data_Descriptor_Class to tell generic memory handling, + * such as the size of the type, how to allocate memory, strings, + * lists, hashes and so on. + * + * - #Eet_Data_Descriptor to tell inside such type, the members and + * their offsets inside the memory blob, their types and + * names. These members can be simple types or other + * #Eet_Data_Descriptor, allowing hierarchical types to be + * defined. + * + * Given that C provides no introspection, this process can be + * quite cumbersome, so we provide lots of macros and convenience + * functions to aid creating the types. + * + * We make now a quick overview of some of the most commonly used elements + * of this part of the library. A simple example of a configuration system + * will work as a somewhat real life example that is still simple enough to + * follow. + * Only the relevant sections will be shown here, but you can get the full + * code @ref eet-data-simple.c "here". + * + * Ignoring the included headers, we'll begin by defining our configuration + * struct. + * @dontinclude eet-data-simple.c + * @skip typedef + * @until } + * + * When using Eet, you don't think in matters of what data the program needs + * to run and which you would like to store. It's all the same and if it makes + * more sense to keep them together, it's perfectly fine to do so. At the time + * of telling Eet how your data is comprised you can leave out the things + * that are runtime only and let Eet take care of the rest for you. + * + * The key used to store the config follows, as well as the variable used to + * store our data descriptor. + * This last one is very important. It's the one thing that Eet will use to + * identify your data, both at the time of writing it to the file and when + * loading from it. + * @skipline MY_CONF + * @skipline Eet_Data_Descriptor + * + * Now we'll see how to create this descriptor, so Eet knows how to handle + * our data later on. + * Begin our function by declaring an Eet_Data_Descriptor_Class, which is + * used to create the actual descriptor. This class contains the name of + * our data type, its size and several functions that dictate how Eet should + * handle memory to allocate the necessary bits to bring our data to life. + * You, as a user, will very hardly set this class' contents directly. The + * most common scenario is to use one of the provided macros that set it using + * the Eina data types, so that's what we'll be doing across all our examples. + * @skip static void + * @until eet_data_descriptor_stream_new + * + * Now that we have our descriptor, we need to make it describe something. + * We do so by telling it which members of our struct we want it to know about + * and their types. + * The eet_data_descriptor_element_add() function takes care of this, but it's + * too cumbersome for normal use, so several macros are provided that make + * it easier to handle. Even with them, however, code can get very repetitive + * and it's not uncommon to define custom macros using them to save on typing. + * @skip #define + * @until } + * + * Now our descriptor knows about the parts of our structure that we are + * interesting in saving. You can see that not all of them are there, yet Eet + * will find those that need saving and do the right thing. When loading our + * data, any non-described fields in the structure will be zeroed, so there's + * no need to worry about garbage memory in them. + * Refer to the documentation of #EET_DATA_DESCRIPTOR_ADD_BASIC to understand + * what our macro does. + * + * We are done with our descriptor init function and it's proper to have the + * relevant shutdown. Proper coding guidelines indiciate that all memory + * allocated should be freed when the program ends, and since you will most + * likely keep your descriptor around for the life or your application, it's + * only right to free it at the end. + * @skip static void + * @until } + * + * Not listed here, but included in the full example are functions to create + * a blank configuration and free it. The first one will only be used when + * no file exists to load from, or nothing is found in it, but the latter is + * used regardless of where our data comes from. Unless you are reading direct + * data from the Eet file, you will be in charge of freeing anything loaded + * from it. + * + * Now it's time to look at how we can load our config from some file. + * Begin by opening the Eet file normally. + * @skip static My_Conf_Type + * @until } + * + * And now we need to read the data from the file and decode it using our + * descriptor. Fortunately, that's all done in one single step. + * @until goto + * + * And that's it for all Eet cares about. But since we are dealing with a + * common case, as is save and load of user configurations, the next fragment + * of code shows why we have a version field in our struct, and how you can + * use it to load older configuration files and update them as needed. + * @until } + * + * Finally, close the file and return the newly loaded config data. + * @until } + * + * Saving data is just as easy. The full version of the following function + * includes code to save to a temporary file first, so you can be sure not + * to lose all your data in the case of a failure mid-writing. You can look + * at it @ref eet-data-simple.c "here". + * @skip static Eina_Bool + * @until { + * @skipline Eina_Bool ret + * @skip eet_open + * @until eet_close + * @skip return + * @until } + * + * To close, our main function, which doesn't do much. Just take some arguments + * from the command line with the name of the file to load and another one + * where to save again. If input file doesn't exist, a new config structure + * will be created and saved to our output file. + * @skip int main + * @until return ret + * @until } + * + * The following is a list of more advanced and detailed examples. + * @li @ref eet_data_nested_example + * @li @ref eet_data_file_descriptor + * @li @ref Example_Eet_Data_File_Descriptor_02 + * @li @ref Example_Eet_Data_Cipher_Decipher + */ + +/** + * @page eet_data_nested_example Nested structures and Eet Data Descriptors + * + * We've seen already a simple example of how to use Eet Data Descriptors + * to handle our structures, but it didn't show how this works when you + * have structures inside other structures. + * + * Now, there's a very simple case of this, for when you have inline structs + * to keep your big structure more organized, you don't need anything else + * besides what @ref eet-data-simple.c "this simple example does". + * Just use something like @p some_struct.sub_struct.member when adding the + * member to the descriptor and it will work. + * + * For example: + * @code + * typedef struct + * { + * int a_number; + * char *a_string; + * struct { + * int other_num; + * int one_more; + * } sub; + * } some_struct; + * + * void some_function() + * { + * ... + * my_desc = eet_data_descriptor_stream_new(&eddc); + * EET_DATA_DESCRIPTOR_ADD_BASIC(my_desc, some_struct, "a_number", + * a_number, EET_T_INT); + * EET_DATA_DESCRIPTOR_ADD_BASIC(my_desc, some_struct, "a_string", + * a_string, EET_T_STRING); + * EET_DATA_DESCRIPTOR_ADD_BASIC(my_desc, some_struct, "sub.other_num", + * sub.other_num, EET_T_INT); + * EET_DATA_DESCRIPTOR_ADD_BASIC(my_desc, some_struct, "sub.one_more", + * sub.one_more", EET_T_INT); + * ... + * } + * @endcode + * + * But this is not what we are here for today. When we talk about nested + * structures, what we really want are things like lists and hashes to be + * taken into consideration automatically, and all their contents saved and + * loaded just like ordinary integers and strings are. + * + * And of course, Eet can do that, and considering the work it saves you as a + * programmer, we could say it's even easier to do than handling just integers. + * + * Let's begin with our example then, which is not all too different from the + * simple one introduced earlier. + * + * We won't ignore the headers this time to show how easy it is to use Eina + * data types with Eet, but we'll still skip most of the code that is not + * pertinent to what we want to show now, but as usual, you can get it full + * by following @ref eet-data-nested.c "this link". + * + * @dontinclude eet-data-nested.c + * @skipline Eina.h + * @skipline Eet.h + * @skip typedef struct + * @until } My_Conf_Subtype + * + * Extremely similar to our previous example. Just a new struct in there, and + * a pointer to a list in the one we already had. Handling a list of subtypes + * is easy on our program, but now we'll see what Eet needs to work with them + * (Hint: it's easy too). + * @skip _my_conf_descriptor + * @until _my_conf_sub_descriptor + * + * Since we have two structures now, it's only natural that we'll need two + * descriptors. One for each, which will be defined exactly as before. + * @skip static void + * @until eddc + * @skip EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET + * @until _my_conf_sub_descriptor + * + * We create our descriptors, each for one type, and as before, we are going to + * use a simple macro to set their contents, to save on typing. + * @skip #define + * @until EET_T_UCHAR + * + * So far, nothing new. We have our descriptors and we know already how to + * save them separately. But what we want is to link them together, and even + * more so, we want our main type to hold a list of more than one of the new + * sub type. So how do we do that? + * + * Simple enough, we tell Eet that our main descriptor will hold a list, of + * which each node will point to some type described by our new descriptor. + * @skip EET_DATA_DESCRIPTOR_ADD_LIST + * @until _my_conf_sub_descriptor + * + * And that's all. We are closing the function now so as to not leave dangling + * curly braces, but there's nothing more to show in this example. Only other + * additions are the necessary code to free our new data, but you can see it + * in the full code listing. + * @until } + */ + +/** + * @page eet_data_file_descriptor Advanced use of Eet Data Descriptors + * + * A real life example is usually the best way to see how things are used, + * but they also involve a lot more code than what needs to be shown, so + * instead of going that way, we'll be borrowing some pieces from one in + * the following example. It's been slightly modified from the original + * source to show more of the varied ways in which Eet can handle our data. + * + * @ref eet-data-file_descriptor_01.c "This example" shows a cache of user + * accounts and messages received, and it's a bit more interactive than + * previous examples. + * + * Let's begin by looking at the structures we'll be using. First we have + * one to define the messages the user receives and one for the one he posts. + * Straight forward and nothing new here. + * @dontinclude eet-data-file_descriptor_01.c + * @skip typedef + * @until My_Post + * + * One more to declare the account itself. This one will contain a list of + * all messages received, and the posts we make ourselves will be kept in an + * array. No special reason other than to show how to use arrays with Eet. + * @until My_Account + * + * Finally, the main structure to hold our cache of accounts. We'll be looking + * for these accounts by their names, so let's keep them in a hash, using + * that name as the key. + * @until My_Cache + * + * As explained before, we need one descriptor for each struct we want Eet + * to handle, but this time we also want to keep around our Eet file and its + * string dictionary. You will see why in a moment. + * @skip Eet_Data_Descriptor + * @until _my_post_descriptor + * @skip Eet_File + * @until Eet_Dictionary + * + * The differences begin now. They aren't much, but we'll be creating our + * descriptors differently. Things can be added to our cache, but we won't + * be modifying the current contents, so we can consider the data read from + * it to be read-only, and thus allow Eet to save time and memory by not + * duplicating thins unnecessary. + * @skip static void + * @until _my_post_descriptor + * + * As the comment in the code explains, we are asking Eet to give us strings + * directly from the mapped file, which avoids having to load it in memory + * and data duplication. + * Of course, there are things to take into account when doing things this + * way, and they will be mentioned as we encounter those special cases. + * + * Next comes the actual description of our data, just like we did in the + * previous examples. + * @skip #define + * @until #undef + * @until #define + * @until #undef + * + * And the account struct's description doesn't add much new, but it's worth + * commenting on it. + * @skip #define + * @until _my_post_descriptor + * + * How to add a list we've seen before, but now we are also adding an array. + * There's nothing really special about it, but it's important to note that + * the EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY is used to add arrays of variable + * length to a descriptor. That is, arrays just like the one we defined. + * Since there's no way in C to know how long they are, we need to keep + * track of the count ourselves and Eet needs to know how to do so as well. + * That's what the @p posts_count member of our struct is for. When adding + * our array member, this macro will look for another variable in the struct + * named just like the array, but with @p _count attached to the end. + * When saving our data, Eet will know how many elements the array contains + * by looking into this count variable. When loading back from a file, this + * variable will be set to the right number of elements. + * + * Another option for arrays is to use EET_DATA_DESCRIPTOR_ADD_ARRAY, which + * takes care of fixed sized arrays. + * For example, let's suppose that we want to keep track of only the last + * ten posts the user sent, and we declare our account struct as follows + * @code + * typedef struct + * { + * unsigned int id; + * const char *name; + * Eina_List *messages; + * My_Post posts[10]; + * } My_Account; + * @endcode + * Then we would add the array to our descriptor with + * @code + * EET_DATA_DESCRIPTOR_ADD_ARRAY(_my_account_descriptor, My_Account, "posts", + * posts, _my_post_descriptor); + * @endcode + * + * Notice how this time we don't have a @p posts_count variable in our struct. + * We could have it for the program to keep track of how many posts the + * array actually contains, but Eet no longer needs it. Being defined that + * way the array is already taking up all the memory needed for the ten + * elements, and it is possible in C to determine how much it is in code. + * When saving our data, Eet will just dump the entire memory blob into the + * file, regardless of how much of it is really used. So it's important to + * take into consideration this kind of things when defining your data types. + * Each has its uses, its advantages and disadvantages and it's up to you + * to decide which to use. + * + * Now, going back to our example, we have to finish adding our data to the + * descriptors. We are only missing the main one for the cache, which + * contains our hash of accounts. + * Unless you are using your own hash functions when setting the descriptor + * class, always use hashes with string type keys. + * @skip #define + * @until } + * + * If you remember, we told Eet not to duplicate memory when possible at the + * time of loading back our data. But this doesn't mean everything will be + * loaded straight from disk and we don't have to worry about freeing it. + * Data in the Eet file is compressed and encoded, so it still needs to be + * decoded and memory will be allocated to convert it back into something we + * can use. We also need to take care of anything we add in the current + * instance of the program. + * To summarize, any string we get from Eet is likely to be a pointer to the + * internal dictionary, and trying to free it will, in the best case, crash + * our application right away. + * + * So how do we know if we have to free a string? We check if it's part of + * the dictionary, and if it's not there we can be sure it's safe to get + * rid of it. + * @skip static void + * @skip } + * @skip static void + * @until } + * + * See how this is used when adding a new message to our cache. + * @skip static My_Message + * @until return msg + * @until free(msg) + * @until } + * + * Skipping all the utility functions used by our program (remember you can + * look at the full example @ref eet-data-file_descriptor_01.c "here") we get to + * our cache loading code. Nothing out of the ordinary at first, just the + * same old open file, read data using our main descriptor to decode it + * into something we can use and check version of loaded data and if it doesn't + * match, do something accordingly. + * @skip static My_Cache + * @until } + * @until } + * @until } + * + * Then comes the interesting part. Remember how we kept two more global + * variables with our descriptors? One of them we already used to check if + * it was right to free a string or not, but we didn't know where it came from. + * Loading our data straight from the mmapped file means that we can't close + * it until we are done using it, so we need to keep its handler around until + * then. It also means that any changes done to the file can, and will, + * invalidate all our pointers to the file backed data, so if we add something + * and save the file, we need to reload our cache. + * + * Thus our load function checks if we had an open file, if there is it gets + * closed and our variable is updated to the new handler. Then we get the + * string dictionary we use to check if a string is part of it or not. + * Updating any references to the cache data is up you as a programmer to + * handle properly, there's nothing Eet can do in this situation. + * @until } + * + * The save function doesn't have anything new, and all that's left after it + * is the main program, which doesn't really have anything of interest within + * the scope of what we are learning. + */ + +/** + * @addtogroup Eet_Data_Group + * @{ + */ +#define EET_T_UNKNOW 0 /**< Unknown data encoding type */ +#define EET_T_CHAR 1 /**< Data type: char */ +#define EET_T_SHORT 2 /**< Data type: short */ +#define EET_T_INT 3 /**< Data type: int */ +#define EET_T_LONG_LONG 4 /**< Data type: long long */ +#define EET_T_FLOAT 5 /**< Data type: float */ +#define EET_T_DOUBLE 6 /**< Data type: double */ +#define EET_T_UCHAR 7 /**< Data type: unsigned char */ +#define EET_T_USHORT 8 /**< Data type: unsigned short */ +#define EET_T_UINT 9 /**< Data type: unsigned int */ +#define EET_T_ULONG_LONG 10 /**< Data type: unsigned long long */ +#define EET_T_STRING 11 /**< Data type: char * */ +#define EET_T_INLINED_STRING 12 /**< Data type: char * (but compressed inside the resulting eet) */ +#define EET_T_NULL 13 /**< Data type: (void *) (only use it if you know why) */ +#define EET_T_F32P32 14 /**< Data type: fixed point 32.32 */ +#define EET_T_F16P16 15 /**< Data type: fixed point 16.16 */ +#define EET_T_F8P24 16 /**< Data type: fixed point 8.24 */ +#define EET_T_LAST 18 /**< Last data type */ + +#define EET_G_UNKNOWN 100 /**< Unknown group data encoding type */ +#define EET_G_ARRAY 101 /**< Fixed size array group type */ +#define EET_G_VAR_ARRAY 102 /**< Variable size array group type */ +#define EET_G_LIST 103 /**< Linked list group type */ +#define EET_G_HASH 104 /**< Hash table group type */ +#define EET_G_UNION 105 /**< Union group type */ +#define EET_G_VARIANT 106 /**< Selectable subtype group */ +#define EET_G_LAST 107 /**< Last group type */ + +#define EET_I_LIMIT 128 /**< Other type exist but are reserved for internal purpose. */ + +/** + * @typedef Eet_Data_Descriptor + * + * Opaque handle that have information on a type members. + * + * Descriptors are created using an #Eet_Data_Descriptor_Class, and they + * describe the contents of the structure that will be serialized by Eet. + * Not all members need be described by it, just those that should be handled + * by Eet. This way it's possible to have one structure with both data to be + * saved to a file, like application configuration, and runtime information + * that would be meaningless to store, but is appropriate to keep together + * during the program execution. + * The members are added by means of + * EET_DATA_DESCRIPTOR_ADD_BASIC(), EET_DATA_DESCRIPTOR_ADD_SUB(), + * EET_DATA_DESCRIPTOR_ADD_LIST(), EET_DATA_DESCRIPTOR_ADD_HASH() + * or eet_data_descriptor_element_add(). + * + * @see eet_data_descriptor_stream_new() + * @see eet_data_descriptor_file_new() + * @see eet_data_descriptor_free() + */ +typedef struct _Eet_Data_Descriptor Eet_Data_Descriptor; + +/** + * @def EET_DATA_DESCRIPTOR_CLASS_VERSION + * The version of #Eet_Data_Descriptor_Class at the time of the + * distribution of the sources. One should define this to its + * version member so it is compatible with abi changes, or at least + * will not crash with them. + */ +#define EET_DATA_DESCRIPTOR_CLASS_VERSION 4 + +/** + * @typedef Eet_Data_Descriptor_Class + * + * Instructs Eet about memory management for different needs under + * serialization and parse process. + */ +typedef struct _Eet_Data_Descriptor_Class Eet_Data_Descriptor_Class; + +typedef int (*Eet_Descriptor_Hash_Foreach_Callback_Callback)(void *h, const char *k, void *dt, void *fdt); + +typedef void * (*Eet_Descriptor_Mem_Alloc_Callback)(size_t size); +typedef void (*Eet_Descriptor_Mem_Free_Callback)(void *mem); +typedef char * (*Eet_Descriptor_Str_Alloc_Callback)(const char *str); +typedef void (*Eet_Descriptor_Str_Free_Callback)(const char *str); +typedef void * (*Eet_Descriptor_List_Next_Callback)(void *l); +typedef void * (*Eet_Descriptor_List_Append_Callback)(void *l, void *d); +typedef void * (*Eet_Descriptor_List_Data_Callback)(void *l); +typedef void * (*Eet_Descriptor_List_Free_Callback)(void *l); +typedef void (*Eet_Descriptor_Hash_Foreach_Callback)(void *h, Eet_Descriptor_Hash_Foreach_Callback_Callback func, void *fdt); +typedef void * (*Eet_Descriptor_Hash_Add_Callback)(void *h, const char *k, void *d); +typedef void (*Eet_Descriptor_Hash_Free_Callback)(void *h); +typedef char * (*Eet_Descriptor_Str_Direct_Alloc_Callback)(const char *str); +typedef void (*Eet_Descriptor_Str_Direct_Free_Callback)(const char *str); +typedef const char * (*Eet_Descriptor_Type_Get_Callback)(const void *data, Eina_Bool *unknow); +typedef Eina_Bool (*Eet_Descriptor_Type_Set_Callback)(const char *type, void *data, Eina_Bool unknow); +typedef void * (*Eet_Descriptor_Array_Alloc_Callback)(size_t size); +typedef void (*Eet_Descriptor_Array_Free_Callback)(void *mem); +/** + * @struct _Eet_Data_Descriptor_Class + * + * Instructs Eet about memory management for different needs under + * serialization and parse process. + * + * The list and hash methods match the Eina API, so for a more detailed + * reference on them, look at the Eina_List and Eina_Hash documentation, + * respectively. + * For the most part these will be used with the standard Eina functions, + * so using EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET() and + * EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET() will set up everything + * accordingly. + */ +struct _Eet_Data_Descriptor_Class +{ + int version; /**< ABI version. Should always be set to #EET_DATA_DESCRIPTOR_CLASS_VERSION */ + const char *name; /**< Name of the user data type to be serialized */ + int size; /**< Size in bytes of the user data type to be serialized */ + struct + { + Eet_Descriptor_Mem_Alloc_Callback mem_alloc; /**< how to allocate memory (usually malloc()) */ + Eet_Descriptor_Mem_Free_Callback mem_free; /**< how to free memory (usually free()) */ + Eet_Descriptor_Str_Alloc_Callback str_alloc; /**< how to allocate a string */ + Eet_Descriptor_Str_Free_Callback str_free; /**< how to free a string */ + Eet_Descriptor_List_Next_Callback list_next; /**< how to iterate to the next element of a list. Receives and should return the list node. */ + Eet_Descriptor_List_Append_Callback list_append; /**< how to append data @p d to list which head node is @p l */ + Eet_Descriptor_List_Data_Callback list_data; /**< retrieves the data from node @p l */ + Eet_Descriptor_List_Free_Callback list_free; /**< free all the nodes from the list which head node is @p l */ + Eet_Descriptor_Hash_Foreach_Callback hash_foreach; /**< iterates over all elements in the hash @p h in no specific order */ + Eet_Descriptor_Hash_Add_Callback hash_add; /**< add a new data @p d with key @p k in hash @p h */ + Eet_Descriptor_Hash_Free_Callback hash_free; /**< free all entries from the hash @p h */ + Eet_Descriptor_Str_Direct_Alloc_Callback str_direct_alloc; /**< how to allocate a string directly from file backed/mmaped region pointed by @p str */ + Eet_Descriptor_Str_Direct_Free_Callback str_direct_free; /**< how to free a string returned by str_direct_alloc */ + 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. */ + 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 */ + Eet_Descriptor_Array_Alloc_Callback array_alloc; /**< how to allocate memory for array (usually malloc()) */ + Eet_Descriptor_Array_Free_Callback array_free; /**< how to free memory for array (usually free()) */ + } func; +}; + +/** + * @} + */ + +/** + * Create a new empty data structure descriptor. + * @param name The string name of this data structure (most be a + * global constant and never change). + * @param size The size of the struct (in bytes). + * @param func_list_next The function to get the next list node. + * @param func_list_append The function to append a member to a list. + * @param func_list_data The function to get the data from a list node. + * @param func_list_free The function to free an entire linked list. + * @param func_hash_foreach The function to iterate through all + * hash table entries. + * @param func_hash_add The function to add a member to a hash table. + * @param func_hash_free The function to free an entire hash table. + * @return A new empty data descriptor. + * + * This function creates a new data descriptor and returns a handle to the + * new data descriptor. On creation it will be empty, containing no contents + * describing anything other than the shell of the data structure. + * + * You add structure members to the data descriptor using the macros + * EET_DATA_DESCRIPTOR_ADD_BASIC(), EET_DATA_DESCRIPTOR_ADD_SUB() and + * EET_DATA_DESCRIPTOR_ADD_LIST(), depending on what type of member you are + * adding to the description. + * + * Once you have described all the members of a struct you want loaded, or + * saved eet can load and save those members for you, encode them into + * endian-independent serialised data chunks for transmission across a + * a network or more. + * + * The function pointers to the list and hash table functions are only + * needed if you use those data types, else you can pass NULL instead. + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + * + * @deprecated use eet_data_descriptor_stream_new() or + * eet_data_descriptor_file_new() + */ +EINA_DEPRECATED EAPI Eet_Data_Descriptor * +eet_data_descriptor_new(const char *name, + int size, + Eet_Descriptor_List_Next_Callback func_list_next, + Eet_Descriptor_List_Append_Callback func_list_append, + Eet_Descriptor_List_Data_Callback func_list_data, + Eet_Descriptor_List_Free_Callback func_list_free, + Eet_Descriptor_Hash_Foreach_Callback func_hash_foreach, + Eet_Descriptor_Hash_Add_Callback func_hash_add, + Eet_Descriptor_Hash_Free_Callback func_hash_free); +/* + * FIXME: + * + * moving to this api from the old above. this will break things when the + * move happens - but be warned + */ +EINA_DEPRECATED EAPI Eet_Data_Descriptor * + eet_data_descriptor2_new(const Eet_Data_Descriptor_Class *eddc); +EINA_DEPRECATED EAPI Eet_Data_Descriptor * + eet_data_descriptor3_new(const Eet_Data_Descriptor_Class *eddc); + +/** + * This function creates a new data descriptor and returns a handle to the + * new data descriptor. On creation it will be empty, containing no contents + * describing anything other than the shell of the data structure. + * @param eddc The class from where to create the data descriptor. + * @return A handle to the new data descriptor. + * + * You add structure members to the data descriptor using the macros + * EET_DATA_DESCRIPTOR_ADD_BASIC(), EET_DATA_DESCRIPTOR_ADD_SUB() and + * EET_DATA_DESCRIPTOR_ADD_LIST(), depending on what type of member you are + * adding to the description. + * + * Once you have described all the members of a struct you want loaded or + * saved, eet can load and save those members for you, encode them into + * endian-independent serialised data chunks for transmission across a + * network or more. + * + * This function specially ignores str_direct_alloc and str_direct_free. It + * is useful when the eet_data you are reading doesn't have a dictionary, + * like network stream or IPC. It also mean that all string will be allocated + * and duplicated in memory. + * + * @since 1.2.3 + * @ingroup Eet_Data_Group + */ +EAPI Eet_Data_Descriptor * +eet_data_descriptor_stream_new(const Eet_Data_Descriptor_Class *eddc); + +/** + * This function creates a new data descriptor and returns a handle to the + * new data descriptor. On creation it will be empty, containing no contents + * describing anything other than the shell of the data structure. + * @param eddc The class from where to create the data descriptor. + * @return A handle to the new data descriptor. + * + * You add structure members to the data descriptor using the macros + * EET_DATA_DESCRIPTOR_ADD_BASIC(), EET_DATA_DESCRIPTOR_ADD_SUB() and + * EET_DATA_DESCRIPTOR_ADD_LIST(), depending on what type of member you are + * adding to the description. + * + * Once you have described all the members of a struct you want loaded or + * saved, eet can load and save those members for you, encode them into + * endian-independent serialised data chunks for transmission across a + * a network or more. + * + * This function uses str_direct_alloc and str_direct_free. It is + * useful when the eet_data you are reading come from a file and + * have a dictionary. This will reduce memory use and improve the + * possibility for the OS to page this string out. + * However, the load speed and memory saving comes with some drawbacks to keep + * in mind. If you never modify the contents of the structures loaded from + * the file, all you need to remember is that closing the eet file will make + * the strings go away. On the other hand, should you need to free a string, + * before doing so you have to verify that it's not part of the eet dictionary. + * You can do this in the following way, assuming @p ef is a valid Eet_File + * and @p str is a string loaded from said file. + * + * @code + * void eet_string_free(Eet_File *ef, const char *str) + * { + * Eet_Dictionary *dict = eet_dictionary_get(ef); + * if (dict && eet_dictionary_string_check(dict, str)) + * { + * // The file contains a dictionary and the given string is a part of + * // of it, so we can't free it, just return. + * return; + * } + * // We assume eina_stringshare was used on the descriptor + * eina_stringshare_del(str); + * } + * @endcode + * + * @since 1.2.3 + * @ingroup Eet_Data_Group + */ +EAPI Eet_Data_Descriptor * +eet_data_descriptor_file_new(const Eet_Data_Descriptor_Class *eddc); + +/** + * This function is an helper that set all the parameters of an + * Eet_Data_Descriptor_Class correctly when you use Eina data type + * with a stream. + * @param eddc The Eet_Data_Descriptor_Class you want to set. + * @param eddc_size The size of the Eet_Data_Descriptor_Class at the compilation time. + * @param name The name of the structure described by this class. + * @param size The size of the structure described by this class. + * @return EINA_TRUE if the structure was correctly set (The only + * reason that could make it fail is if you did give wrong + * parameter). + * + * @note Unless there's a very specific reason to use this function directly, + * the EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET macro is recommended. + * + * @since 1.2.3 + * @ingroup Eet_Data_Group + */ +EAPI Eina_Bool +eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, + unsigned int eddc_size, + const char *name, + int size); + +/** + * This macro is an helper that set all the parameter of an + * Eet_Data_Descriptor_Class correctly when you use Eina data type + * with stream. + * @param clas The Eet_Data_Descriptor_Class you want to set. + * @param type The type of the structure described by this class. + * @return EINA_TRUE if the structure was correctly set (The only + * reason that could make it fail is if you did give wrong + * parameter). + * + * @see eet_data_descriptor_stream_new + * @since 1.2.3 + * @ingroup Eet_Data_Group + */ +#define EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(clas, type) \ + (eet_eina_stream_data_descriptor_class_set(clas, sizeof (*(clas)), # type, sizeof(type))) + +/** + * This function is an helper that set all the parameter of an + * Eet_Data_Descriptor_Class correctly when you use Eina data type + * with a file. + * @param eddc The Eet_Data_Descriptor_Class you want to set. + * @param eddc_size The size of the Eet_Data_Descriptor_Class at the compilation time. + * @param name The name of the structure described by this class. + * @param size The size of the structure described by this class. + * @return EINA_TRUE if the structure was correctly set (The only + * reason that could make it fail is if you did give wrong + * parameter). + * + * @note Unless there's a very specific reason to use this function directly, + * the EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET macro is recommended. + * + * @since 1.2.3 + * @ingroup Eet_Data_Group + */ +EAPI Eina_Bool +eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, + unsigned int eddc_size, + const char *name, + int size); + +/** + * This macro is an helper that set all the parameter of an + * Eet_Data_Descriptor_Class correctly when you use Eina data type + * with file. + * @param clas The Eet_Data_Descriptor_Class you want to set. + * @param type The type of the structure described by this class. + * @return EINA_TRUE if the structure was correctly set (The only + * reason that could make it fail is if you did give wrong + * parameter). + * + * @see eet_data_descriptor_file_new + * @since 1.2.3 + * @ingroup Eet_Data_Group + */ +#define EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(clas, type) \ + (eet_eina_file_data_descriptor_class_set(clas, sizeof (*(clas)), # type, sizeof(type))) + +/** + * This function frees a data descriptor when it is not needed anymore. + * @param edd The data descriptor to free. + * + * This function takes a data descriptor handle as a parameter and frees all + * data allocated for the data descriptor and the handle itself. After this + * call the descriptor is no longer valid. + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +EAPI void +eet_data_descriptor_free(Eet_Data_Descriptor *edd); + +/** + * This function is an internal used by macros. + * + * This function is used by macros EET_DATA_DESCRIPTOR_ADD_BASIC(), + * EET_DATA_DESCRIPTOR_ADD_SUB() and EET_DATA_DESCRIPTOR_ADD_LIST(). It is + * complex to use by hand and should be left to be used by the macros, and + * thus is not documented. + * + * @param edd The data descriptor handle to add element (member). + * @param name The name of element to be serialized. + * @param type The type of element to be serialized, like + * #EET_T_INT. If #EET_T_UNKNOW, then it is considered to be a + * group, list or hash. + * @param group_type If element type is #EET_T_UNKNOW, then the @p + * group_type will specify if it is a list (#EET_G_LIST), + * array (#EET_G_ARRAY) and so on. If #EET_G_UNKNOWN, then + * the member is a subtype (pointer to another type defined by + * another #Eet_Data_Descriptor). + * @param offset byte offset inside the source memory to be serialized. + * @param count number of elements (if #EET_G_ARRAY or #EET_G_VAR_ARRAY). + * @param counter_name variable that defines the name of number of elements. + * @param subtype If contains a subtype, then its data descriptor. + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +EAPI void +eet_data_descriptor_element_add(Eet_Data_Descriptor *edd, + const char *name, + int type, + int group_type, + int offset, + /* int count_offset, */ + int count, + const char *counter_name, + Eet_Data_Descriptor *subtype); + +/** + * Read a data structure from an eet file and decodes it. + * @param ef The eet file handle to read from. + * @param edd The data descriptor handle to use when decoding. + * @param name The key the data is stored under in the eet file. + * @return A pointer to the decoded data structure. + * + * This function decodes a data structure stored in an eet file, returning + * a pointer to it if it decoded successfully, or NULL on failure. This + * can save a programmer dozens of hours of work in writing configuration + * file parsing and writing code, as eet does all that work for the program + * and presents a program-friendly data structure, just as the programmer + * likes. Eet can handle members being added or deleted from the data in + * storage and safely zero-fills unfilled members if they were not found + * in the data. It checks sizes and headers whenever it reads data, allowing + * the programmer to not worry about corrupt data. + * + * Once a data structure has been described by the programmer with the + * fields they wish to save or load, storing or retrieving a data structure + * from an eet file, or from a chunk of memory is as simple as a single + * function call. + * + * @see eet_data_read_cipher() + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +EAPI void * +eet_data_read(Eet_File *ef, + Eet_Data_Descriptor *edd, + const char *name); + +/** + * Write a data structure from memory and store in an eet file. + * @param ef The eet file handle to write to. + * @param edd The data descriptor to use when encoding. + * @param name The key to store the data under in the eet file. + * @param data A pointer to the data structure to save and encode. + * @param compress Compression flags for storage. + * @return bytes written on successful write, 0 on failure. + * + * This function is the reverse of eet_data_read(), saving a data structure + * to an eet file. The file must have been opening in write mode and the data + * will be kept in memory until the file is either closed or eet_sync() is + * called to flush any unwritten changes. + * + * @see eet_data_write_cipher() + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +EAPI int +eet_data_write(Eet_File *ef, + Eet_Data_Descriptor *edd, + const char *name, + const void *data, + int compress); + +typedef void (*Eet_Dump_Callback)(void *data, const char *str); + +/** + * Dump an eet encoded data structure into ascii text + * @param data_in The pointer to the data to decode into a struct. + * @param size_in The size of the data pointed to in bytes. + * @param dumpfunc The function to call passed a string when new + * data is converted to text + * @param dumpdata The data to pass to the @p dumpfunc callback. + * @return 1 on success, 0 on failure + * + * This function will take a chunk of data encoded by + * eet_data_descriptor_encode() and convert it into human readable + * ascii text. It does this by calling the @p dumpfunc callback + * for all new text that is generated. This callback should append + * to any existing text buffer and will be passed the pointer @p + * dumpdata as a parameter as well as a string with new text to be + * appended. + * + * Example: + * + * @code + * void output(void *data, const char *string) + * { + * printf("%s", string); + * } + * + * void dump(const char *file) + * { + * FILE *f; + * int len; + * void *data; + * + * f = fopen(file, "r"); + * fseek(f, 0, SEEK_END); + * len = ftell(f); + * rewind(f); + * data = malloc(len); + * fread(data, len, 1, f); + * fclose(f); + * eet_data_text_dump(data, len, output, NULL); + * } + * @endcode + * + * @see eet_data_text_dump_cipher() + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +EAPI int +eet_data_text_dump(const void *data_in, + int size_in, + Eet_Dump_Callback dumpfunc, + void *dumpdata); + +/** + * Take an ascii encoding from eet_data_text_dump() and re-encode in binary. + * @param text The pointer to the string data to parse and encode. + * @param textlen The size of the string in bytes (not including 0 + * byte terminator). + * @param size_ret This gets filled in with the encoded data blob + * size in bytes. + * @return The encoded data on success, NULL on failure. + * + * This function will parse the string pointed to by @p text and return + * an encoded data lump the same way eet_data_descriptor_encode() takes an + * in-memory data struct and encodes into a binary blob. @p text is a normal + * C string. + * + * @see eet_data_text_undump_cipher() + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +EAPI void * +eet_data_text_undump(const char *text, + int textlen, + int *size_ret); + +/** + * Dump an eet encoded data structure from an eet file into ascii text + * @param ef A valid eet file handle. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param dumpfunc The function to call passed a string when new + * data is converted to text + * @param dumpdata The data to pass to the @p dumpfunc callback. + * @return 1 on success, 0 on failure + * + * This function will take an open and valid eet file from + * eet_open() request the data encoded by + * eet_data_descriptor_encode() corresponding to the key @p name + * and convert it into human readable ascii text. It does this by + * calling the @p dumpfunc callback for all new text that is + * generated. This callback should append to any existing text + * buffer and will be passed the pointer @p dumpdata as a parameter + * as well as a string with new text to be appended. + * + * @see eet_data_dump_cipher() + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +EAPI int +eet_data_dump(Eet_File *ef, + const char *name, + Eet_Dump_Callback dumpfunc, + void *dumpdata); + +/** + * Take an ascii encoding from eet_data_dump() and re-encode in binary. + * @param ef A valid eet file handle. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param text The pointer to the string data to parse and encode. + * @param textlen The size of the string in bytes (not including 0 + * byte terminator). + * @param compress Compression flags (1 == compress, 0 = don't compress). + * @return 1 on success, 0 on failure + * + * This function will parse the string pointed to by @p text, + * encode it the same way eet_data_descriptor_encode() takes an + * in-memory data struct and encodes into a binary blob. + * + * The data (optionally compressed) will be in ram, pending a flush to + * disk (it will stay in ram till the eet file handle is closed though). + * + * @see eet_data_undump_cipher() + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +EAPI int +eet_data_undump(Eet_File *ef, + const char *name, + const char *text, + int textlen, + int compress); + +/** + * Decode a data structure from an arbitrary location in memory. + * @param edd The data descriptor to use when decoding. + * @param data_in The pointer to the data to decode into a struct. + * @param size_in The size of the data pointed to in bytes. + * @return NULL on failure, or a valid decoded struct pointer on success. + * + * This function will decode a data structure that has been encoded using + * eet_data_descriptor_encode(), and return a data structure with all its + * elements filled out, if successful, or NULL on failure. + * + * The data to be decoded is stored at the memory pointed to by @p data_in, + * and is described by the descriptor pointed to by @p edd. The data size is + * passed in as the value to @p size_in, ande must be greater than 0 to + * succeed. + * + * This function is useful for decoding data structures delivered to the + * application by means other than an eet file, such as an IPC or socket + * connection, raw files, shared memory etc. + * + * Please see eet_data_read() for more information. + * + * @see eet_data_descriptor_decode_cipher() + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +EAPI void * +eet_data_descriptor_decode(Eet_Data_Descriptor *edd, + const void *data_in, + int size_in); + +/** + * Encode a dsata struct to memory and return that encoded data. + * @param edd The data descriptor to use when encoding. + * @param data_in The pointer to the struct to encode into data. + * @param size_ret pointer to the an int to be filled with the decoded size. + * @return NULL on failure, or a valid encoded data chunk on success. + * + * This function takes a data structutre in memory and encodes it into a + * serialised chunk of data that can be decoded again by + * eet_data_descriptor_decode(). This is useful for being able to transmit + * data structures across sockets, pipes, IPC or shared file mechanisms, + * without having to worry about memory space, machine type, endianness etc. + * + * The parameter @p edd must point to a valid data descriptor, and + * @p data_in must point to the right data structure to encode. If not, the + * encoding may fail. + * + * On success a non NULL valid pointer is returned and what @p size_ret + * points to is set to the size of this decoded data, in bytes. When the + * encoded data is no longer needed, call free() on it. On failure NULL is + * returned and what @p size_ret points to is set to 0. + * + * Please see eet_data_write() for more information. + * + * @see eet_data_descriptor_encode_cipher() + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +EAPI void * +eet_data_descriptor_encode(Eet_Data_Descriptor *edd, + const void *data_in, + int *size_ret); + +/** + * Add a basic data element to a data descriptor. + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * @param type The type of the member to encode. + * + * This macro is a convenience macro provided to add a member to + * the data descriptor @p edd. The type of the structure is + * provided as the @p struct_type parameter (for example: struct + * my_struct). The @p name parameter defines a string that will be + * used to uniquely name that member of the struct (it is suggested + * to use the struct member itself). The @p member parameter is + * the actual struct member itself (for example: values), and @p type is the + * basic data type of the member which must be one of: EET_T_CHAR, EET_T_SHORT, + * EET_T_INT, EET_T_LONG_LONG, EET_T_FLOAT, EET_T_DOUBLE, EET_T_UCHAR, + * EET_T_USHORT, EET_T_UINT, EET_T_ULONG_LONG or EET_T_STRING. + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +#define EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct_type, name, member, type) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, name, type, EET_G_UNKNOWN, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + 0, /* 0, */ NULL, NULL); \ + } while(0) + +/** + * Add a sub-element type to a data descriptor + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * @param subtype The type of sub-type struct to add. + * + * This macro lets you easily add a sub-type (a struct that's pointed to + * by this one). All the parameters are the same as for + * EET_DATA_DESCRIPTOR_ADD_BASIC(), with the @p subtype being the exception. + * This must be the data descriptor of the struct that is pointed to by + * this element. + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +#define EET_DATA_DESCRIPTOR_ADD_SUB(edd, struct_type, name, member, subtype) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_UNKNOWN, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + 0, /* 0, */ NULL, subtype); \ + } while (0) + +/** + * Add a linked list type to a data descriptor + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * @param subtype The type of linked list member to add. + * + * This macro lets you easily add a linked list of other data types. All the + * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(), with the + * @p subtype being the exception. This must be the data descriptor of the + * element that is in each member of the linked list to be stored. + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +#define EET_DATA_DESCRIPTOR_ADD_LIST(edd, struct_type, name, member, subtype) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_LIST, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + 0, /* 0, */ NULL, subtype); \ + } while (0) + +/** + * Add a linked list of string to a data descriptor + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * + * This macro lets you easily add a linked list of char *. All the + * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(). + * + * @since 1.5.0 + * @ingroup Eet_Data_Group + */ +#define EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd, struct_type, name, member) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, name, EET_T_STRING, EET_G_LIST, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + 0, /* 0, */ NULL, NULL); \ + } while (0) + +/** + * Add a hash type to a data descriptor + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * @param subtype The type of hash member to add. + * + * This macro lets you easily add a hash of other data types. All the + * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(), with the + * @p subtype being the exception. This must be the data descriptor of the + * element that is in each member of the hash to be stored. + * The hash keys must be strings. + * + * @since 1.0.0 + * @ingroup Eet_Data_Group + */ +#define EET_DATA_DESCRIPTOR_ADD_HASH(edd, struct_type, name, member, subtype) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_HASH, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + 0, /* 0, */ NULL, subtype); \ + } while (0) + +/** + * Add a hash of string to a data descriptor + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * + * This macro lets you easily add a hash of string elements. All the + * parameters are the same as for EET_DATA_DESCRIPTOR_ADD_HASH(). + * + * @since 1.3.4 + * @ingroup Eet_Data_Group + */ +#define EET_DATA_DESCRIPTOR_ADD_HASH_STRING(edd, struct_type, name, member) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, name, EET_T_STRING, EET_G_HASH, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + 0, /* 0, */ NULL, NULL); \ + } while (0) + +/** + * Add an array of basic data elements to a data descriptor. + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * @param type The type of the member to encode. + * + * This macro lets you easily add a fixed size array of basic data + * types. All the parameters are the same as for + * EET_DATA_DESCRIPTOR_ADD_BASIC(). + * The array must be defined with a fixed size in the declaration of the + * struct containing it. + * + * @since 1.5.0 + * @ingroup Eet_Data_Group + */ +#define EET_DATA_DESCRIPTOR_ADD_BASIC_ARRAY(edd, struct_type, name, member, type) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, name, type, EET_G_ARRAY, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + sizeof(___ett.member) / \ + sizeof(___ett.member[0]), \ + NULL, NULL); \ + } while(0) + +/** + * Add a variable array of basic data elements to a data descriptor. + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * @param type The type of the member to encode. + * + * This macro lets you easily add a variable size array of basic data + * types. All the parameters are the same as for + * EET_DATA_DESCRIPTOR_ADD_BASIC(). This assumes you have + * a struct member (of type EET_T_INT) called member_count (note the + * _count appended to the member) that holds the number of items in + * the array. This array will be allocated separately to the struct it + * is in. + * + * @since 1.6.0 + * @ingroup Eet_Data_Group + */ +#define EET_DATA_DESCRIPTOR_ADD_BASIC_VAR_ARRAY(edd, struct_type, name, member, type) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, name, type, EET_G_VAR_ARRAY, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + (char *)(& (___ett.member ## _count)) - \ + (char *)(& (___ett)), \ + NULL, \ + NULL); \ + } while(0) + +/** + * Add a fixed size array type to a data descriptor + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * @param subtype The type of hash member to add. + * + * This macro lets you easily add a fixed size array of other data + * types. All the parameters are the same as for + * EET_DATA_DESCRIPTOR_ADD_BASIC(), with the @p subtype being the + * exception. This must be the data descriptor of the element that + * is in each member of the array to be stored. + * The array must be defined with a fixed size in the declaration of the + * struct containing it. + * + * @since 1.0.2 + * @ingroup Eet_Data_Group + */ +#define EET_DATA_DESCRIPTOR_ADD_ARRAY(edd, struct_type, name, member, subtype) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_ARRAY, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + /* 0, */ sizeof(___ett.member) / \ + sizeof(___ett.member[0]), NULL, subtype); \ + } while (0) + +/** + * Add a variable size array type to a data descriptor + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * @param subtype The type of hash member to add. + * + * This macro lets you easily add a variable size array of other data + * types. All the parameters are the same as for + * EET_DATA_DESCRIPTOR_ADD_BASIC(), with the @p subtype being the + * exception. This must be the data descriptor of the element that + * is in each member of the array to be stored. This assumes you have + * a struct member (of type EET_T_INT) called member_count (note the + * _count appended to the member) that holds the number of items in + * the array. This array will be allocated separately to the struct it + * is in. + * + * @since 1.0.2 + * @ingroup Eet_Data_Group + */ +#define EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(edd, struct_type, name, member, subtype) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, \ + name, \ + EET_T_UNKNOW, \ + EET_G_VAR_ARRAY, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + (char *)(& (___ett.member ## _count)) - \ + (char *)(& (___ett)), \ + /* 0, */ NULL, \ + subtype); \ + } while (0) + +/** + * Add a variable size array type to a data descriptor + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * + * This macro lets you easily add a variable size array of strings. All + * the parameters are the same as for EET_DATA_DESCRIPTOR_ADD_BASIC(). + * + * @since 1.4.0 + * @ingroup Eet_Data_Group + */ +#define EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY_STRING(edd, struct_type, name, member) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, \ + name, \ + EET_T_STRING, \ + EET_G_VAR_ARRAY, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + (char *)(& (___ett.member ## _count)) - \ + (char *)(& (___ett)), \ + /* 0, */ NULL, \ + NULL); \ + } while (0) + +/** + * Add an union type to a data descriptor + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * @param type_member The member that give hints on what is in the union. + * @param unified_type Describe all possible type the union could handle. + * + * This macro lets you easily add an union with a member that specify what is inside. + * The @p unified_type is an Eet_Data_Descriptor, but only the entry that match the name + * returned by type_get will be used for each serialized data. The type_get and type_set + * callback of unified_type should be defined. + * + * @since 1.2.4 + * @ingroup Eet_Data_Group + * @see Eet_Data_Descriptor_Class + */ +#define EET_DATA_DESCRIPTOR_ADD_UNION(edd, struct_type, name, member, type_member, unified_type) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_UNION, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + (char *)(& (___ett.type_member)) - \ + (char *)(& (___ett)), \ + NULL, unified_type); \ + } while (0) + +/** + * Add a automatically selectable type to a data descriptor + * @param edd The data descriptor to add the type to. + * @param struct_type The type of the struct. + * @param name The string name to use to encode/decode this member + * (must be a constant global and never change). + * @param member The struct member itself to be encoded. + * @param type_member The member that give hints on what is in the union. + * @param unified_type Describe all possible type the union could handle. + * + * This macro lets you easily define what the content of @p member points to depending of + * the content of @p type_member. The type_get and type_set callback of unified_type should + * be defined. If the the type is not know at the time of restoring it, eet will still call + * type_set of @p unified_type but the pointer will be set to a serialized binary representation + * of what eet know. This make it possible, to save this pointer again by just returning the string + * given previously and telling it by setting unknow to EINA_TRUE. + * + * @since 1.2.4 + * @ingroup Eet_Data_Group + * @see Eet_Data_Descriptor_Class + */ +#define EET_DATA_DESCRIPTOR_ADD_VARIANT(edd, struct_type, name, member, type_member, unified_type) \ + do { \ + struct_type ___ett; \ + eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_VARIANT, \ + (char *)(& (___ett.member)) - \ + (char *)(& (___ett)), \ + (char *)(& (___ett.type_member)) - \ + (char *)(& (___ett)), \ + NULL, unified_type); \ + } while (0) + +/** + * Add a mapping to a data descriptor that will be used by union, variant or inherited type + * @param unified_type The data descriptor to add the mapping to. + * @param name The string name to get/set type. + * @param subtype The matching data descriptor. + * + * @since 1.2.4 + * @ingroup Eet_Data_Group + * @see Eet_Data_Descriptor_Class + */ +#define EET_DATA_DESCRIPTOR_ADD_MAPPING(unified_type, name, subtype) \ + eet_data_descriptor_element_add(unified_type, \ + name, \ + EET_T_UNKNOW, \ + EET_G_UNKNOWN, \ + 0, \ + 0, \ + NULL, \ + subtype) + +/** + * @defgroup Eet_Data_Cipher_Group Eet Data Serialization using A Ciphers + * + * Most of the @ref Eet_Data_Group have alternative versions that + * accounts for ciphers to protect their content. + * + * @see @ref Eet_Cipher_Group + * + * @ingroup Eet_Data_Group + */ + +/** + * Read a data structure from an eet file and decodes it using a cipher. + * @param ef The eet file handle to read from. + * @param edd The data descriptor handle to use when decoding. + * @param name The key the data is stored under in the eet file. + * @param cipher_key The key to use as cipher. + * @return A pointer to the decoded data structure. + * + * This function decodes a data structure stored in an eet file, returning + * a pointer to it if it decoded successfully, or NULL on failure. This + * can save a programmer dozens of hours of work in writing configuration + * file parsing and writing code, as eet does all that work for the program + * and presents a program-friendly data structure, just as the programmer + * likes. Eet can handle members being added or deleted from the data in + * storage and safely zero-fills unfilled members if they were not found + * in the data. It checks sizes and headers whenever it reads data, allowing + * the programmer to not worry about corrupt data. + * + * Once a data structure has been described by the programmer with the + * fields they wish to save or load, storing or retrieving a data structure + * from an eet file, or from a chunk of memory is as simple as a single + * function call. + * + * @see eet_data_read() + * + * @since 1.0.0 + * @ingroup Eet_Data_Cipher_Group + */ +EAPI void * +eet_data_read_cipher(Eet_File *ef, + Eet_Data_Descriptor *edd, + const char *name, + const char *cipher_key); + +/** + * Read a data structure from an eet extended attribute and decodes it using a cipher. + * @param filename The file to extract the extended attribute from. + * @param attribute The attribute to get the data from. + * @param edd The data descriptor handle to use when decoding. + * @param cipher_key The key to use as cipher. + * @return A pointer to the decoded data structure. + * + * This function decodes a data structure stored in an eet extended attribute, + * returning a pointer to it if it decoded successfully, or NULL on failure. + * Eet can handle members being added or deleted from the data in + * storage and safely zero-fills unfilled members if they were not found + * in the data. It checks sizes and headers whenever it reads data, allowing + * the programmer to not worry about corrupt data. + * + * Once a data structure has been described by the programmer with the + * fields they wish to save or load, storing or retrieving a data structure + * from an eet file, from a chunk of memory or from an extended attribute + * is as simple as a single function call. + * + * @since 1.5.0 + * @ingroup Eet_Data_Cipher_Group + */ +EAPI void * +eet_data_xattr_cipher_get(const char *filename, + const char *attribute, + Eet_Data_Descriptor *edd, + const char *cipher_key); + +/** + * Write a data structure from memory and store in an eet file + * using a cipher. + * @param ef The eet file handle to write to. + * @param edd The data descriptor to use when encoding. + * @param name The key to store the data under in the eet file. + * @param cipher_key The key to use as cipher. + * @param data A pointer to the data structure to save and encode. + * @param compress Compression flags for storage. + * @return bytes written on successful write, 0 on failure. + * + * This function is the reverse of eet_data_read_cipher(), saving a data structure + * to an eet file. + * + * @since 1.0.0 + * @ingroup Eet_Data_Cipher_Group + */ +EAPI int +eet_data_write_cipher(Eet_File *ef, + Eet_Data_Descriptor *edd, + const char *name, + const char *cipher_key, + const void *data, + int compress); + +/** + * Write a data structure from memory and store in an eet extended attribute + * using a cipher. + * @param filename The file to write the extended attribute to. + * @param attribute The attribute to store the data to. + * @param edd The data descriptor to use when encoding. + * @param cipher_key The key to use as cipher. + * @param data A pointer to the data structure to save and encode. + * @param flags The policy to use when setting the data. + * @return EINA_TRUE on success, EINA_FALSE on failure. + * + * This function is the reverse of eet_data_xattr_cipher_get(), saving a data structure + * to an eet extended attribute. + * + * @since 1.5.0 + * @ingroup Eet_Data_Cipher_Group + */ +EAPI Eina_Bool +eet_data_xattr_cipher_set(const char *filename, + const char *attribute, + Eet_Data_Descriptor *edd, + const char *cipher_key, + const void *data, + Eina_Xattr_Flags flags); + +/** + * Dump an eet encoded data structure into ascii text using a cipher. + * @param data_in The pointer to the data to decode into a struct. + * @param cipher_key The key to use as cipher. + * @param size_in The size of the data pointed to in bytes. + * @param dumpfunc The function to call passed a string when new + * data is converted to text + * @param dumpdata The data to pass to the @p dumpfunc callback. + * @return 1 on success, 0 on failure + * + * This function will take a chunk of data encoded by + * eet_data_descriptor_encode() and convert it into human readable + * ascii text. It does this by calling the @p dumpfunc callback + * for all new text that is generated. This callback should append + * to any existing text buffer and will be passed the pointer @p + * dumpdata as a parameter as well as a string with new text to be + * appended. + * + * Example: + * + * @code + * void output(void *data, const char *string) + * { + * printf("%s", string); + * } + * + * void dump(const char *file) + * { + * FILE *f; + * int len; + * void *data; + * + * f = fopen(file, "r"); + * fseek(f, 0, SEEK_END); + * len = ftell(f); + * rewind(f); + * data = malloc(len); + * fread(data, len, 1, f); + * fclose(f); + * eet_data_text_dump_cipher(data, cipher_key, len, output, NULL); + * } + * @endcode + * + * @see eet_data_text_dump() + * + * @since 1.0.0 + * @ingroup Eet_Data_Cipher_Group + */ +EAPI int +eet_data_text_dump_cipher(const void *data_in, + const char *cipher_key, + int size_in, + Eet_Dump_Callback dumpfunc, + void *dumpdata); + +/** + * Take an ascii encoding from eet_data_text_dump() and re-encode + * in binary using a cipher. + * @param text The pointer to the string data to parse and encode. + * @param cipher_key The key to use as cipher. + * @param textlen The size of the string in bytes (not including 0 + * byte terminator). + * @param size_ret This gets filled in with the encoded data blob + * size in bytes. + * @return The encoded data on success, NULL on failure. + * + * This function will parse the string pointed to by @p text and return + * an encoded data lump the same way eet_data_descriptor_encode() takes an + * in-memory data struct and encodes into a binary blob. @p text is a normal + * C string. + * + * @see eet_data_text_undump() + * + * @since 1.0.0 + * @ingroup Eet_Data_Cipher_Group + */ +EAPI void * +eet_data_text_undump_cipher(const char *text, + const char *cipher_key, + int textlen, + int *size_ret); + +/** + * Dump an eet encoded data structure from an eet file into ascii + * text using a cipher. + * @param ef A valid eet file handle. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param cipher_key The key to use as cipher. + * @param dumpfunc The function to call passed a string when new + * data is converted to text + * @param dumpdata The data to pass to the @p dumpfunc callback. + * @return 1 on success, 0 on failure + * + * This function will take an open and valid eet file from + * eet_open() request the data encoded by + * eet_data_descriptor_encode() corresponding to the key @p name + * and convert it into human readable ascii text. It does this by + * calling the @p dumpfunc callback for all new text that is + * generated. This callback should append to any existing text + * buffer and will be passed the pointer @p dumpdata as a parameter + * as well as a string with new text to be appended. + * + * @see eet_data_dump() + * + * @since 1.0.0 + * @ingroup Eet_Data_Cipher_Group + */ +EAPI int +eet_data_dump_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + Eet_Dump_Callback dumpfunc, + void *dumpdata); + +/** + * Take an ascii encoding from eet_data_dump() and re-encode in + * binary using a cipher. + * @param ef A valid eet file handle. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param cipher_key The key to use as cipher. + * @param text The pointer to the string data to parse and encode. + * @param textlen The size of the string in bytes (not including 0 + * byte terminator). + * @param compress Compression flags (1 == compress, 0 = don't compress). + * @return 1 on success, 0 on failure + * + * This function will parse the string pointed to by @p text, + * encode it the same way eet_data_descriptor_encode() takes an + * in-memory data struct and encodes into a binary blob. + * + * The data (optionally compressed) will be in ram, pending a flush to + * disk (it will stay in ram till the eet file handle is closed though). + * + * @see eet_data_undump() + * + * @since 1.0.0 + * @ingroup Eet_Data_Cipher_Group + */ +EAPI int +eet_data_undump_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + const char *text, + int textlen, + int compress); + +/** + * Decode a data structure from an arbitrary location in memory + * using a cipher. + * @param edd The data descriptor to use when decoding. + * @param data_in The pointer to the data to decode into a struct. + * @param cipher_key The key to use as cipher. + * @param size_in The size of the data pointed to in bytes. + * @return NULL on failure, or a valid decoded struct pointer on success. + * + * This function will decode a data structure that has been encoded using + * eet_data_descriptor_encode(), and return a data structure with all its + * elements filled out, if successful, or NULL on failure. + * + * The data to be decoded is stored at the memory pointed to by @p data_in, + * and is described by the descriptor pointed to by @p edd. The data size is + * passed in as the value to @p size_in, ande must be greater than 0 to + * succeed. + * + * This function is useful for decoding data structures delivered to the + * application by means other than an eet file, such as an IPC or socket + * connection, raw files, shared memory etc. + * + * Please see eet_data_read() for more information. + * + * @see eet_data_descriptor_decode() + * + * @since 1.0.0 + * @ingroup Eet_Data_Cipher_Group + */ +EAPI void * +eet_data_descriptor_decode_cipher(Eet_Data_Descriptor *edd, + const void *data_in, + const char *cipher_key, + int size_in); + +/** + * Encode a data struct to memory and return that encoded data + * using a cipher. + * @param edd The data descriptor to use when encoding. + * @param data_in The pointer to the struct to encode into data. + * @param cipher_key The key to use as cipher. + * @param size_ret pointer to the an int to be filled with the decoded size. + * @return NULL on failure, or a valid encoded data chunk on success. + * + * This function takes a data structutre in memory and encodes it into a + * serialised chunk of data that can be decoded again by + * eet_data_descriptor_decode(). This is useful for being able to transmit + * data structures across sockets, pipes, IPC or shared file mechanisms, + * without having to worry about memory space, machine type, endianess etc. + * + * The parameter @p edd must point to a valid data descriptor, and + * @p data_in must point to the right data structure to encode. If not, the + * encoding may fail. + * + * On success a non NULL valid pointer is returned and what @p size_ret + * points to is set to the size of this decoded data, in bytes. When the + * encoded data is no longer needed, call free() on it. On failure NULL is + * returned and what @p size_ret points to is set to 0. + * + * Please see eet_data_write() for more information. + * + * @see eet_data_descriptor_encode() + * + * @since 1.0.0 + * @ingroup Eet_Data_Cipher_Group + */ +EAPI void * +eet_data_descriptor_encode_cipher(Eet_Data_Descriptor *edd, + const void *data_in, + const char *cipher_key, + int *size_ret); + +/** + * @defgroup Eet_Node_Group Low-level Serialization Structures. + * + * Functions that create, destroy and manipulate serialization nodes + * used by @ref Eet_Data_Group. + * + * @{ + */ + +/** + * @typedef Eet_Node + * Opaque handle to manage serialization node. + */ +typedef struct _Eet_Node Eet_Node; + +/** + * @typedef Eet_Node_Data + * Contains an union that can fit any kind of node. + */ +typedef struct _Eet_Node_Data Eet_Node_Data; + +/** + * @struct _Eet_Node_Data + * Contains an union that can fit any kind of node. + */ +struct _Eet_Node_Data +{ + union { + char c; + short s; + int i; + long long l; + float f; + double d; + unsigned char uc; + unsigned short us; + unsigned int ui; + unsigned long long ul; + const char *str; + } value; +}; + +/** + * @} + */ + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_char_new(const char *name, + char c); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_short_new(const char *name, + short s); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_int_new(const char *name, + int i); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_long_long_new(const char *name, + long long l); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_float_new(const char *name, + float f); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_double_new(const char *name, + double d); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_unsigned_char_new(const char *name, + unsigned char uc); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_unsigned_short_new(const char *name, + unsigned short us); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_unsigned_int_new(const char *name, + unsigned int ui); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_unsigned_long_long_new(const char *name, + unsigned long long l); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_string_new(const char *name, + const char *str); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_inlined_string_new(const char *name, + const char *str); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_null_new(const char *name); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_list_new(const char *name, + Eina_List *nodes); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_array_new(const char *name, + int count, + Eina_List *nodes); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_var_array_new(const char *name, + Eina_List *nodes); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_hash_new(const char *name, + const char *key, + Eet_Node *node); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_struct_new(const char *name, + Eina_List *nodes); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_node_struct_child_new(const char *parent, + Eet_Node *child); + +/** + * @brief Get a node's child nodes + * @param node The node + * @return The first child node which contains a pointer to the + * next child node and the parent. + * @since 1.5 + */ +EAPI Eet_Node * +eet_node_children_get(Eet_Node *node); + +/** + * @brief Get the next node in a list of nodes + * @param node The node + * @return A node which contains a pointer to the + * next child node and the parent. + * @since 1.5 + */ +EAPI Eet_Node * +eet_node_next_get(Eet_Node *node); + +/** + * @brief Get the parent node of a node + * @param node The node + * @return The parent node of @p node + * @since 1.5 + */ +EAPI Eet_Node * +eet_node_parent_get(Eet_Node *node); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI void +eet_node_list_append(Eet_Node *parent, + const char *name, + Eet_Node *child); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI void +eet_node_struct_append(Eet_Node *parent, + const char *name, + Eet_Node *child); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI void +eet_node_hash_add(Eet_Node *parent, + const char *name, + const char *key, + Eet_Node *child); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI void +eet_node_dump(Eet_Node *n, + int dumplevel, + Eet_Dump_Callback dumpfunc, + void *dumpdata); + +/** + * @brief Return the type of a node + * @param node The node + * @return The node's type (EET_T_$TYPE) + * @since 1.5 + */ +EAPI int +eet_node_type_get(Eet_Node *node); + +/** + * @brief Return the node's data + * @param node The node + * @return The data contained in the node + * @since 1.5 + */ +EAPI Eet_Node_Data * +eet_node_value_get(Eet_Node *node); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI void +eet_node_del(Eet_Node *n); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI void * +eet_data_node_encode_cipher(Eet_Node *node, + const char *cipher_key, + int *size_ret); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_data_node_decode_cipher(const void *data_in, + const char *cipher_key, + int size_in); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI Eet_Node * +eet_data_node_read_cipher(Eet_File *ef, + const char *name, + const char *cipher_key); + +/** + * TODO FIX ME + * @ingroup Eet_Node_Group + */ +EAPI int +eet_data_node_write_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + Eet_Node *node, + int compress); + +/* EXPERIMENTAL: THIS API MAY CHANGE IN THE FUTURE, USE IT ONLY IF YOU KNOW WHAT YOU ARE DOING. */ + +/** + * @typedef Eet_Node_Walk + * Describes how to walk trees of #Eet_Node. + */ +typedef struct _Eet_Node_Walk Eet_Node_Walk; + +typedef void * (*Eet_Node_Walk_Struct_Alloc_Callback)(const char *type, void *user_data); +typedef void (*Eet_Node_Walk_Struct_Add_Callback)(void *parent, const char *name, void *child, void *user_data); +typedef void * (*Eet_Node_Walk_Array_Callback)(Eina_Bool variable, const char *name, int count, void *user_data); +typedef void (*Eet_Node_Walk_Insert_Callback)(void *array, int index, void *child, void *user_data); +typedef void * (*Eet_Node_Walk_List_Callback)(const char *name, void *user_data); +typedef void (*Eet_Node_Walk_Append_Callback)(void *list, void *child, void *user_data); +typedef void * (*Eet_Node_Walk_Hash_Callback)(void *parent, const char *name, const char *key, void *value, void *user_data); +typedef void * (*Eet_Node_Walk_Simple_Callback)(int type, Eet_Node_Data *data, void *user_data); + +/** + * @struct _Eet_Node_Walk + * Describes how to walk trees of #Eet_Node. + */ +struct _Eet_Node_Walk +{ + Eet_Node_Walk_Struct_Alloc_Callback struct_alloc; + Eet_Node_Walk_Struct_Add_Callback struct_add; + Eet_Node_Walk_Array_Callback array; + Eet_Node_Walk_Insert_Callback insert; + Eet_Node_Walk_List_Callback list; + Eet_Node_Walk_Append_Callback append; + Eet_Node_Walk_Hash_Callback hash; + Eet_Node_Walk_Simple_Callback simple; +}; + +EAPI void * +eet_node_walk(void *parent, + const char *name, + Eet_Node *root, + Eet_Node_Walk *cb, + void *user_data); + +/*******/ + +/** + * @defgroup Eet_Connection_Group Helper function to use eet over a network link + * + * Function that reconstruct and prepare packet of @ref Eet_Data_Group to be send. + * + */ + +/** + * @typedef Eet_Connection + * Opaque handle to track paquet for a specific connection. + * + * @ingroup Eet_Connection_Group + */ +typedef struct _Eet_Connection Eet_Connection; + +/** + * @typedef Eet_Read_Cb + * Called back when an @ref Eet_Data_Group has been received completely and could be used. + * + * @ingroup Eet_Connection_Group + */ +typedef Eina_Bool Eet_Read_Cb (const void *eet_data, size_t size, void *user_data); + +/** + * @typedef Eet_Write_Cb + * Called back when a packet containing @ref Eet_Data_Group data is ready to be send. + * + * @ingroup Eet_Connection_Group + */ +typedef Eina_Bool Eet_Write_Cb (const void *data, size_t size, void *user_data); + +/** + * Instanciate a new connection to track. + * @param eet_read_cb Function to call when one Eet_Data packet has been fully assemble. + * @param eet_write_cb Function to call when one Eet_Data packet is ready to be send over the wire. + * @param user_data Pointer provided to both functions to be used as a context handler. + * @return NULL on failure, or a valid Eet_Connection handler. + * + * For every connection to track you will need a separate Eet_Connection provider. + * + * @since 1.2.4 + * @ingroup Eet_Connection_Group + */ +EAPI Eet_Connection * +eet_connection_new(Eet_Read_Cb *eet_read_cb, + Eet_Write_Cb *eet_write_cb, + const void *user_data); + +/** + * Process a raw packet received over the link + * @param conn Connection handler to track. + * @param data Raw data packet. + * @param size The size of that packet. + * @return 0 on complete success, any other value indicate where in the stream it got wrong (It could be before that packet). + * + * Every time you receive a packet related to your connection, you should pass + * it to that function so that it could process and assemble packet has you + * receive it. It will automatically call Eet_Read_Cb when one is fully received. + * + * @since 1.2.4 + * @ingroup Eet_Connection_Group + */ +EAPI int +eet_connection_received(Eet_Connection *conn, + const void *data, + size_t size); + +/** + * Tell if the Eet_Connection as received some partial data. + * @param conn Connection handler to request. + * @return EINA_TRUE if there is some data pending inside, EINA_FALSE otherwise. + * + * Eet_Connection buffer data until the received data can be unserialized correctly. This + * function let you know if there is some data inside that buffer waiting for more data to + * be received before being processed. + * + * @since 1.7 + * @ingroup Eet_Connection_Group + */ +EAPI Eina_Bool eet_connection_empty(Eet_Connection *conn); + +/** + * Convert a complex structure and prepare it to be send. + * @param conn Connection handler to track. + * @param edd The data descriptor to use when encoding. + * @param data_in The pointer to the struct to encode into data. + * @param cipher_key The key to use as cipher. + * @return EINA_TRUE if the data where correctly send, EINA_FALSE if they don't. + * + * This function serialize data_in with edd, assemble the packet and call + * Eet_Write_Cb when ready. The data passed Eet_Write_Cb are temporary allocated + * and will vanish just after the return of the callback. + * + * @see eet_data_descriptor_encode_cipher + * + * @since 1.2.4 + * @ingroup Eet_Connection_Group + */ +EAPI Eina_Bool +eet_connection_send(Eet_Connection *conn, + Eet_Data_Descriptor *edd, + const void *data_in, + const char *cipher_key); + +/** + * Convert a Eet_Node tree and prepare it to be send. + * @param conn Connection handler to track. + * @param node The data tree to use when encoding. + * @param cipher_key The key to use as cipher. + * @return EINA_TRUE if the data where correctly send, EINA_FALSE if they don't. + * + * This function serialize node, assemble the packet and call + * Eet_Write_Cb when ready. The data passed Eet_Write_Cb are temporary allocated + * and will vanish just after the return of the callback. + * + * @see eet_data_node_encode_cipher + * + * @since 1.2.4 + * @ingroup Eet_Connection_Group + */ +EAPI Eina_Bool +eet_connection_node_send(Eet_Connection *conn, + Eet_Node *node, + const char *cipher_key); + +/** + * Close a connection and lost its track. + * @param conn Connection handler to close. + * @param on_going Signal if a partial packet wasn't completed. + * @return the user_data passed to both callback. + * + * @since 1.2.4 + * @ingroup Eet_Connection_Group + */ +EAPI void * +eet_connection_close(Eet_Connection *conn, + Eina_Bool *on_going); + +/***************************************************************************/ -/***************************************************************************/ #ifdef __cplusplus } -#endif +#endif /* ifdef __cplusplus */ -#endif +#endif /* ifndef _EET_H */ diff --git a/src/lib/Eet_private.h b/src/lib/Eet_private.h index 4af3e2b..20c12d7 100644 --- a/src/lib/Eet_private.h +++ b/src/lib/Eet_private.h @@ -1,84 +1,329 @@ -/* - * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 - */ - #ifndef _EET_PRIVATE_H #define _EET_PRIVATE_H -#ifdef __GNUC__ -# if __GNUC__ >= 4 -// BROKEN in gcc 4 on amd64 -//# pragma GCC visibility push(hidden) -# endif -#endif +#include + +typedef enum _Eet_Convert_Type Eet_Convert_Type; + +enum _Eet_Convert_Type +{ + EET_D_NOTHING = 0, + EET_D_FLOAT = 1 << 1, + EET_D_DOUBLE = 1 << 2, + EET_D_FIXED_POINT = 1 << 4 +}; + +typedef struct _Eet_String Eet_String; +typedef struct _Eet_Convert Eet_Convert; + +struct _Eet_Convert +{ + float f; + double d; + Eina_F32p32 fp; -typedef struct _Eet_String Eet_String; + Eet_Convert_Type type; +}; struct _Eet_String { - const char *mmap; - char *str; - - int hash; - int len; - - int next; - int prev; - - union - { - float f; - double d; - } convert; - - struct - { - unsigned int converted : 1; - unsigned int is_float : 1; - } flags; + const char *str; + + int len; + + int next; + int prev; + + unsigned char hash; + unsigned char allocated : 1; }; struct _Eet_Dictionary { - Eet_String *all; + Eet_String *all; + Eina_Hash *converts; + Eina_Lock mutex; + + int size; + int offset; + + int hash[256]; + + int count; + int total; + + const char *start; + const char *end; +}; + +struct _Eet_Node +{ + int type; + int count; + const char *name; + const char *key; + Eet_Node *values; + Eet_Node *next; + Eet_Node *parent; + Eet_Node_Data data; +}; + +typedef struct _Eet_File_Header Eet_File_Header; +typedef struct _Eet_File_Node Eet_File_Node; +typedef struct _Eet_File_Directory Eet_File_Directory; + +struct _Eet_File +{ + const char *path; + Eina_File *readfp; + Eet_File_Header *header; + Eet_Dictionary *ed; + Eet_Key *key; + const unsigned char *data; + const void *x509_der; + const void *signature; + void *sha1; + + Eet_File_Mode mode; + + int magic; + int references; + + unsigned long int data_size; + int x509_length; + unsigned int signature_length; + int sha1_length; + + Eina_Lock file_lock; + + unsigned char writes_pending : 1; + unsigned char delete_me_now : 1; +}; + +struct _Eet_File_Header +{ + int magic; + Eet_File_Directory *directory; +}; + +struct _Eet_File_Directory +{ + int size; + Eet_File_Node **nodes; +}; - int size; - int offset; +struct _Eet_File_Node +{ + char *name; + void *data; + Eet_File_Node *next; /* FIXME: make buckets linked lists */ - int hash[256]; + unsigned long int offset; + unsigned long int dictionary_offset; + unsigned long int name_offset; - int count; - int total; + unsigned int name_size; + unsigned int size; + unsigned int data_size; - const char *start; - const char *end; + unsigned char compression_type; + + unsigned char free_name : 1; + unsigned char compression : 1; + unsigned char ciphered : 1; + unsigned char alias : 1; }; -Eet_Dictionary *eet_dictionary_add(void); -void eet_dictionary_free(Eet_Dictionary *ed); -int eet_dictionary_string_add(Eet_Dictionary *ed, const char *string); -int eet_dictionary_string_get_size(const Eet_Dictionary *ed, int index); -const char *eet_dictionary_string_get_char(const Eet_Dictionary *ed, int index); -int eet_dictionary_string_get_float(const Eet_Dictionary *ed, int index, float *result); -int eet_dictionary_string_get_double(const Eet_Dictionary *ed, int index, double *result); -int eet_dictionary_string_get_hash(const Eet_Dictionary *ed, int index); - -FILE *_eet_memfile_read_open(const void *data, size_t size); -void _eet_memfile_read_close(FILE *f); -FILE *_eet_memfile_write_open(void **data, size_t *size); -void _eet_memfile_write_close(FILE *f); -void _eet_memfile_shutdown(void); -int _eet_hash_gen(const char *key, int hash_size); -int _eet_string_to_double_convert(const char *src, long long *m, long *e); -void _eet_double_to_string_convert(char des[128], double d); +#if 0 +/* Version 2 */ +/* NB: all int's are stored in network byte order on disk */ +/* file format: */ +int magic; /* magic number ie 0x1ee7ff00 */ +int num_directory_entries; /* number of directory entries to follow */ +int bytes_directory_entries; /* bytes of directory entries to follow */ +struct +{ + int offset; /* bytes offset into file for data chunk */ + int flags; /* flags - for now 0 = uncompressed and clear, 1 = compressed and clear, 2 = uncompressed and ciphered, 3 = compressed and ciphered */ + int size; /* size of the data chunk */ + int data_size; /* size of the (uncompressed) data chunk */ + int name_size; /* length in bytes of the name field */ + char name[name_size]; /* name string (variable length) and \0 terminated */ +} directory[num_directory_entries]; +/* and now startes the data stream... */ +#endif /* if 0 */ + +#if 0 +/* Version 3 */ +/* NB: all int's are stored in network byte order on disk */ +/* file format: */ +int magic; /* magic number ie 0x1ee70f42 */ +int num_directory_entries; /* number of directory entries to follow */ +int num_dictionary_entries; /* number of dictionary entries to follow */ +struct +{ + int data_offset; /* bytes offset into file for data chunk */ + int size; /* size of the data chunk */ + int data_size; /* size of the (uncompressed) data chunk */ + int name_offset; /* bytes offset into file for name string */ + int name_size; /* length in bytes of the name field */ + int flags; /* bit flags - for now: + bit 0 => compresion on/off + bit 1 => ciphered on/off + bit 2 => alias + */ +} directory[num_directory_entries]; +struct +{ + int hash; + int offset; + int size; + int prev; + int next; +} dictionary[num_dictionary_entries]; +/* now start the string stream. */ +/* and right after them the data stream. */ +int magic_sign; /* Optional, only if the eet file is signed. */ +int signature_length; /* Signature length. */ +int x509_length; /* Public certificate that signed the file. */ +char signature[signature_length]; /* The signature. */ +char x509[x509_length]; /* The public certificate. */ +#endif /* if 0 */ + +/* + * variable and macros used for the eina_log module + */ +extern int _eet_log_dom_global; + +/* + * Macros that are used everywhere + * + * the first four macros are the general macros for the lib + */ +#ifdef EET_DEFAULT_LOG_COLOR +# undef EET_DEFAULT_LOG_COLOR +#endif /* ifdef EET_DEFAULT_LOG_COLOR */ +#define EET_DEFAULT_LOG_COLOR EINA_COLOR_CYAN +#ifdef ERR +# undef ERR +#endif /* ifdef ERR */ +#define ERR(...) EINA_LOG_DOM_ERR(_eet_log_dom_global, __VA_ARGS__) +#ifdef DBG +# undef DBG +#endif /* ifdef DBG */ +#define DBG(...) EINA_LOG_DOM_DBG(_eet_log_dom_global, __VA_ARGS__) +#ifdef INF +# undef INF +#endif /* ifdef INF */ +#define INF(...) EINA_LOG_DOM_INFO(_eet_log_dom_global, __VA_ARGS__) +#ifdef WRN +# undef WRN +#endif /* ifdef WRN */ +#define WRN(...) EINA_LOG_DOM_WARN(_eet_log_dom_global, __VA_ARGS__) +#ifdef CRIT +# undef CRIT +#endif /* ifdef CRIT */ +#define CRIT(...) EINA_LOG_DOM_CRIT(_eet_log_dom_global, __VA_ARGS__) + +Eet_Dictionary * + eet_dictionary_add(void); +void + eet_dictionary_free(Eet_Dictionary *ed); +int + eet_dictionary_string_add(Eet_Dictionary *ed, + const char *string); +int +eet_dictionary_string_get_size(const Eet_Dictionary *ed, + int index); +const char * +eet_dictionary_string_get_char(const Eet_Dictionary *ed, + int index); +Eina_Bool +eet_dictionary_string_get_float(const Eet_Dictionary *ed, + int index, + float *result); +Eina_Bool +eet_dictionary_string_get_double(const Eet_Dictionary *ed, + int index, + double *result); +Eina_Bool +eet_dictionary_string_get_fp(const Eet_Dictionary *ed, + int index, + Eina_F32p32 *result); +int +eet_dictionary_string_get_hash(const Eet_Dictionary *ed, + int index); + +int _eet_hash_gen(const char *key, + int hash_size); + +const void * +eet_identity_check(const void *data_base, + unsigned int data_length, + void **sha1, + int *sha1_length, + const void *signature_base, + unsigned int signature_length, + const void **raw_signature_base, + unsigned int *raw_signature_length, + int *x509_length); +void * +eet_identity_compute_sha1(const void *data_base, + unsigned int data_length, + int *sha1_length); +Eet_Error +eet_cipher(const void *data, + unsigned int size, + const char *key, + unsigned int length, + void **result, + unsigned int *result_length); +Eet_Error +eet_decipher(const void *data, + unsigned int size, + const char *key, + unsigned int length, + void **result, + unsigned int *result_length); +Eet_Error +eet_identity_sign(FILE *fp, + Eet_Key *key); +void + eet_identity_unref(Eet_Key *key); +void + eet_identity_ref(Eet_Key *key); + +void + eet_node_shutdown(void); +int + eet_node_init(void); +Eet_Node * + eet_node_new(void); +void + eet_node_free(Eet_Node *node); + + +#define GENERIC_ALLOC_FREE_HEADER(TYPE, Type) \ + TYPE *Type##_malloc(unsigned int); \ + TYPE *Type##_calloc(unsigned int); \ + void Type##_mp_free(TYPE *e); + +GENERIC_ALLOC_FREE_HEADER(Eet_File_Directory, eet_file_directory); +GENERIC_ALLOC_FREE_HEADER(Eet_File_Node, eet_file_node); +GENERIC_ALLOC_FREE_HEADER(Eet_File_Header, eet_file_header); +GENERIC_ALLOC_FREE_HEADER(Eet_Dictionary, eet_dictionary); +GENERIC_ALLOC_FREE_HEADER(Eet_File, eet_file); + +Eina_Bool eet_mempool_init(void); +void eet_mempool_shutdown(void); #ifndef PATH_MAX -#define PATH_MAX 4096 -#endif +# define PATH_MAX 4096 +#endif /* ifndef PATH_MAX */ #ifdef DNDEBUG -#define EET_ASSERT(Test, Do) if (Test == 0) Do; -#else -#define EET_ASSERT(Test, Do) if (Test == 0) abort(); -#endif +# define EET_ASSERT(Test, Do) if (Test == 0) {Do; } +#else /* ifdef DNDEBUG */ +# define EET_ASSERT(Test, Do) if (Test == 0) {abort(); } +#endif /* ifdef DNDEBUG */ -#endif +#endif /* ifndef _EET_PRIVATE_H */ diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 4141f7a..438aecc 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -4,30 +4,39 @@ MAINTAINERCLEANFILES = Makefile.in AM_CPPFLAGS = \ -I. \ -I$(top_srcdir)/src/lib \ +-I$(top_srcdir)/src/lib/lz4 \ +-I$(top_builddir)/src/lib \ -DPACKAGE_BIN_DIR=\"$(bindir)\" \ -DPACKAGE_LIB_DIR=\"$(libdir)\" \ -DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ -@EVIL_CFLAGS@ \ -@COVERAGE_CFLAGS@ +@EET_CFLAGS@ \ +@EFL_EET_BUILD@ -include_HEADERS = Eet.h +includes_HEADERS = Eet.h +includesdir = $(includedir)/eet-@VMAJ@ lib_LTLIBRARIES = libeet.la -libeet_la_SOURCES = \ -eet_lib.c \ +libeet_la_SOURCES = \ +Eet_private.h \ +eet_alloc.c \ +eet_cipher.c \ +eet_connection.c \ eet_data.c \ -eet_image.c \ -eet_memfile.c \ eet_dictionary.c \ -eet_utils.c +eet_image.c \ +eet_lib.c \ +eet_node.c \ +eet_utils.c \ +lz4/lz4.c \ +lz4/lz4.h \ +lz4/lz4hc.c \ +lz4/lz4hc.h -libeet_la_CFLAGS = @WIN32_CFLAGS@ -libeet_la_LIBADD = @COVERAGE_LIBS@ @EVIL_LIBS@ @WIN32_LIBS@ -lz -ljpeg @fnmatch_libs@ -lm -libeet_la_LDFLAGS = @lt_no_undefined@ @lt_enable_auto_import@ -version-info @version_info@ -libeet_la_DEPENDENCIES = $(top_builddir)/config.h +libeet_la_LIBADD = @EET_LIBS@ -lm +libeet_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@ -EXTRA_DIST = Eet_private.h +EXTRA_DIST = lz4/README clean-local: - @rm -rf *.gcno + @rm -rf *.gcno eet_amalgamation.c diff --git a/src/lib/eet_alloc.c b/src/lib/eet_alloc.c new file mode 100644 index 0000000..310b1bf --- /dev/null +++ b/src/lib/eet_alloc.c @@ -0,0 +1,93 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "Eet.h" +#include "Eet_private.h" + +typedef struct _Eet_Mempool Eet_Mempool; +struct _Eet_Mempool +{ + const char *name; + Eina_Mempool *mp; + size_t size; +}; + +#define GENERIC_ALLOC_FREE(TYPE, Type) \ + Eet_Mempool Type##_mp = { #TYPE, NULL, sizeof (TYPE) }; \ + \ + TYPE * \ + Type##_malloc(unsigned int num) \ + { \ + return eina_mempool_malloc(Type##_mp.mp, num * sizeof (TYPE)); \ + } \ + TYPE * \ + Type##_calloc(unsigned int num) \ + { \ + return eina_mempool_calloc(Type##_mp.mp, num * sizeof (TYPE)); \ + } \ + void \ + Type##_mp_free(TYPE *e) \ + { \ + eina_mempool_free(Type##_mp.mp, e); \ + } + +GENERIC_ALLOC_FREE(Eet_File_Directory, eet_file_directory); +GENERIC_ALLOC_FREE(Eet_File_Node, eet_file_node); +GENERIC_ALLOC_FREE(Eet_File_Header, eet_file_header); +GENERIC_ALLOC_FREE(Eet_Dictionary, eet_dictionary); +GENERIC_ALLOC_FREE(Eet_File, eet_file); + +static Eet_Mempool *mempool_array[] = { + &eet_file_directory_mp, + &eet_file_node_mp, + &eet_file_header_mp, + &eet_dictionary_mp, + &eet_file_mp, +}; + +Eina_Bool +eet_mempool_init(void) +{ + const char *choice; + unsigned int i; + + choice = getenv("EINA_MEMPOOL"); + if ((!choice) || (!choice[0])) + choice = "chained_mempool"; + + for (i = 0; i < sizeof (mempool_array) / sizeof (mempool_array[0]); ++i) + { + retry: + mempool_array[i]->mp = eina_mempool_add(choice, mempool_array[i]->name, NULL, mempool_array[i]->size, 16); + if (!mempool_array[i]->mp) + { + if (!(!strcmp(choice, "pass_through"))) + { + ERR("Falling back to pass through ! Previously tried '%s' mempool.", choice); + choice = "pass_through"; + goto retry; + } + else + { + ERR("Impossible to allocate mempool '%s' !", choice); + return EINA_FALSE; + } + } + } + return EINA_TRUE; +} + +void +eet_mempool_shutdown(void) +{ + unsigned int i; + + for (i = 0; i < sizeof (mempool_array) / sizeof (mempool_array[0]); ++i) + { + eina_mempool_del(mempool_array[i]->mp); + mempool_array[i]->mp = NULL; + } +} diff --git a/src/lib/eet_cipher.c b/src/lib/eet_cipher.c new file mode 100644 index 0000000..5bd9f25 --- /dev/null +++ b/src/lib/eet_cipher.c @@ -0,0 +1,1391 @@ +#ifdef HAVE_CONFIG_H +# include +#endif /* ifdef HAVE_CONFIG_H */ + +#ifdef HAVE_ALLOCA_H +# include +#elif defined __GNUC__ +# define alloca __builtin_alloca +#elif defined _AIX +# define alloca __alloca +#elif defined _MSC_VER +# include +# define alloca _alloca +#else /* ifdef HAVE_ALLOCA_H */ +# include +# ifdef __cplusplus +extern "C" +# endif /* ifdef __cplusplus */ +void *alloca(size_t); +#endif /* ifdef HAVE_ALLOCA_H */ + +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif /* ifdef HAVE_UNISTD_H */ + +#ifdef HAVE_NETINET_IN_H +# include +#endif /* ifdef HAVE_NETINET_IN_H */ + +#ifdef HAVE_SIGNATURE +# include +# ifdef HAVE_GNUTLS +# include +# include +# else /* ifdef HAVE_GNUTLS */ +# include +# include +# include +# include +# include +# include +# include +# include +# include +# endif /* ifdef HAVE_GNUTLS */ +#endif /* ifdef HAVE_SIGNATURE */ + +#ifdef HAVE_OPENSSL +# include +#endif /* ifdef HAVE_OPENSSL */ + +#ifdef HAVE_CIPHER +# ifdef HAVE_GNUTLS +# if defined EET_USE_NEW_PUBKEY_VERIFY_HASH || defined EET_USE_NEW_PRIVKEY_SIGN_DATA +# include +# endif +# include +# include +# else /* ifdef HAVE_GNUTLS */ +# include +# include +# include +# endif /* ifdef HAVE_GNUTLS */ +#endif /* ifdef HAVE_CIPHER */ + +#include "Eet.h" +#include "Eet_private.h" + +#define EET_MAGIC_SIGN 0x1ee74271 + +#ifdef HAVE_GNUTLS +# define MAX_KEY_LEN 32 +# define MAX_IV_LEN 16 +#else /* ifdef HAVE_GNUTLS */ +# define MAX_KEY_LEN EVP_MAX_KEY_LENGTH +# define MAX_IV_LEN EVP_MAX_IV_LENGTH +#endif /* ifdef HAVE_GNUTLS */ + +#ifdef HAVE_CIPHER +# ifdef HAVE_GNUTLS +static Eet_Error +eet_hmac_sha1(const void *key, + size_t key_len, + const void *data, + size_t data_len, + unsigned char *res); +# endif /* ifdef HAVE_GNUTLS */ +static Eet_Error +eet_pbkdf2_sha1(const char *key, + int key_len, + const unsigned char *salt, + unsigned int salt_len, + int iter, + unsigned char *res, + int res_len); +#endif /* ifdef HAVE_CIPHER */ + +struct _Eet_Key +{ + int references; +#ifdef HAVE_SIGNATURE +# ifdef HAVE_GNUTLS + gnutls_x509_crt_t certificate; + gnutls_x509_privkey_t private_key; +# else /* ifdef HAVE_GNUTLS */ + X509 *certificate; + EVP_PKEY *private_key; +# endif /* ifdef HAVE_GNUTLS */ +#endif /* ifdef HAVE_SIGNATURE */ +}; + +EAPI Eet_Key * +eet_identity_open(const char *certificate_file, + const char *private_key_file, + Eet_Key_Password_Callback cb) +{ +#ifdef HAVE_SIGNATURE + /* Signature declarations */ + Eet_Key *key = NULL; +# ifdef HAVE_GNUTLS + /* Gnutls private declarations */ + Eina_File *f = NULL; + void *data = NULL; + gnutls_datum_t load_file = { NULL, 0 }; + char pass[1024]; + + /* Init */ + if (!(key = malloc(sizeof(Eet_Key)))) + goto on_error; + + key->references = 1; + + if (gnutls_x509_crt_init(&(key->certificate))) + goto on_error; + + if (gnutls_x509_privkey_init(&(key->private_key))) + goto on_error; + + /* Mmap certificate_file */ + f = eina_file_open(certificate_file, 0); + if (!f) + goto on_error; + + /* let's make mmap safe and just get 0 pages for IO erro */ + eina_mmap_safety_enabled_set(EINA_TRUE); + + data = eina_file_map_all(f, EINA_FILE_SEQUENTIAL); + if (!data) goto on_error; + + /* Import the certificate in Eet_Key structure */ + load_file.data = data; + load_file.size = eina_file_size_get(f); + if (gnutls_x509_crt_import(key->certificate, &load_file, + GNUTLS_X509_FMT_PEM) < 0) + goto on_error; + + eina_file_map_free(f, data); + + /* Reset values */ + eina_file_close(f); + f = NULL; + data = NULL; + load_file.data = NULL; + load_file.size = 0; + + /* Mmap private_key_file */ + f = eina_file_open(private_key_file, 0); + if (!f) + goto on_error; + + /* let's make mmap safe and just get 0 pages for IO erro */ + eina_mmap_safety_enabled_set(EINA_TRUE); + + data = eina_file_map_all(f, EINA_FILE_SEQUENTIAL); + if (!data) + goto on_error; + + /* Import the private key in Eet_Key structure */ + load_file.data = data; + load_file.size = eina_file_size_get(f); + /* Try to directly import the PEM encoded private key */ + if (gnutls_x509_privkey_import(key->private_key, &load_file, + GNUTLS_X509_FMT_PEM) < 0) + { + /* Else ask for the private key pass */ + if (cb && cb(pass, 1024, 0, NULL)) + { + /* If pass then try to decode the pkcs 8 private key */ + if (gnutls_x509_privkey_import_pkcs8(key->private_key, &load_file, + GNUTLS_X509_FMT_PEM, pass, 0)) + goto on_error; + } + else + /* Else try to import the pkcs 8 private key without pass */ + if (gnutls_x509_privkey_import_pkcs8(key->private_key, &load_file, + GNUTLS_X509_FMT_PEM, NULL, 1)) + goto on_error; + } + + eina_file_map_free(f, data); + eina_file_close(f); + + return key; + +on_error: + if (data) eina_file_map_free(f, data); + if (f) eina_file_close(f); + + if (key) + { + if (key->certificate) + gnutls_x509_crt_deinit(key->certificate); + + if (key->private_key) + gnutls_x509_privkey_deinit(key->private_key); + + free(key); + } + +# else /* ifdef HAVE_GNUTLS */ + /* Openssl private declarations */ + FILE *fp; + EVP_PKEY *pkey = NULL; + X509 *cert = NULL; + + /* Load the X509 certificate in memory. */ + fp = fopen(certificate_file, "r"); + if (!fp) + return NULL; + + cert = PEM_read_X509(fp, NULL, NULL, NULL); + fclose(fp); + if (!cert) + goto on_error; + + /* Check the presence of the public key. Just in case. */ + pkey = X509_get_pubkey(cert); + if (!pkey) + goto on_error; + + /* Load the private key in memory. */ + fp = fopen(private_key_file, "r"); + if (!fp) + goto on_error; + + pkey = PEM_read_PrivateKey(fp, NULL, cb, NULL); + fclose(fp); + if (!pkey) + goto on_error; + + /* Load the certificate and the private key in Eet_Key structure */ + key = malloc(sizeof(Eet_Key)); + if (!key) + goto on_error; + + key->references = 1; + key->certificate = cert; + key->private_key = pkey; + + return key; + +on_error: + if (cert) + X509_free(cert); + + if (pkey) + EVP_PKEY_free(pkey); + +# endif /* ifdef HAVE_GNUTLS */ +#else + certificate_file = NULL; + private_key_file = NULL; + cb = NULL; +#endif /* ifdef HAVE_SIGNATURE */ + return NULL; +} + +EAPI void +eet_identity_close(Eet_Key *key) +{ +#ifdef HAVE_SIGNATURE + if (!key || (key->references > 0)) + return; + +# ifdef HAVE_GNUTLS + gnutls_x509_crt_deinit(key->certificate); + gnutls_x509_privkey_deinit(key->private_key); +# else /* ifdef HAVE_GNUTLS */ + X509_free(key->certificate); + EVP_PKEY_free(key->private_key); +# endif /* ifdef HAVE_GNUTLS */ + free(key); +#else + key = NULL; +#endif /* ifdef HAVE_SIGNATURE */ +} + +EAPI void +eet_identity_print(Eet_Key *key, + FILE *out) +{ +#ifdef HAVE_SIGNATURE +# ifdef HAVE_GNUTLS + const char *names[6] = { + "Modulus", + "Public exponent", + "Private exponent", + "First prime", + "Second prime", + "Coefficient" + }; + int err = 0; + gnutls_datum_t data = { NULL, 0 }; + gnutls_datum_t rsa_raw[6]; + size_t size = 128; + char *res = NULL; + char buf[33]; + unsigned int i, j; + + if (!key) + return; + + if (key->private_key) + { + if (gnutls_x509_privkey_export_rsa_raw(key->private_key, + rsa_raw + 0, /* Modulus */ + rsa_raw + 1, /* Public exponent */ + rsa_raw + 2, /* Private exponent */ + rsa_raw + 3, /* First prime */ + rsa_raw + 4, /* Second prime */ + rsa_raw + 5)) /* Coefficient */ + goto on_error; + + if (!(res = malloc(size))) + goto on_error; + + fprintf(out, "Private Key:\n"); + buf[32] = '\0'; + + for (i = 0; i < 6; i++) + { + while ((err = gnutls_hex_encode(rsa_raw + i, res, &size)) == + GNUTLS_E_SHORT_MEMORY_BUFFER) + { + size += 128; + if (!(res = realloc(res, size))) + goto on_error; + } + if (err) + goto on_error; + + fprintf(out, "\t%s:\n", names[i]); + for (j = 0; strlen(res) > j; j += 32) + { + snprintf(buf, 32, "%s", res + j); + fprintf(out, "\t\t%s\n", buf); + } + } + free(res); + res = NULL; + } + + if (key->certificate) + { + fprintf(out, "Public certificate:\n"); + if (gnutls_x509_crt_print(key->certificate, GNUTLS_X509_CRT_FULL, + &data)) + goto on_error; + + fprintf(out, "%s\n", data.data); + gnutls_free(data.data); + data.data = NULL; + } + +on_error: + if (res) + free(res); + + if (data.data) + gnutls_free(data.data); + + return; +# else /* ifdef HAVE_GNUTLS */ + RSA *rsa; + DSA *dsa; + DH *dh; + + if (!key) + return; + + rsa = EVP_PKEY_get1_RSA(key->private_key); + if (rsa) + { + fprintf(out, "Private key (RSA):\n"); + RSA_print_fp(out, rsa, 0); + } + + dsa = EVP_PKEY_get1_DSA(key->private_key); + if (dsa) + { + fprintf(out, "Private key (DSA):\n"); + DSA_print_fp(out, dsa, 0); + } + + dh = EVP_PKEY_get1_DH(key->private_key); + if (dh) + { + fprintf(out, "Private key (DH):\n"); + DHparams_print_fp(out, dh); + } + + fprintf(out, "Public certificate:\n"); + X509_print_fp(out, key->certificate); +# endif /* ifdef HAVE_GNUTLS */ +#else /* ifdef HAVE_SIGNATURE */ + key = NULL; + out = NULL; + ERR("You need to compile signature support in EET."); +#endif /* ifdef HAVE_SIGNATURE */ +} + +void +eet_identity_ref(Eet_Key *key) +{ + if (!key) + return; + + key->references++; +} + +void +eet_identity_unref(Eet_Key *key) +{ + if (!key) + return; + + key->references--; + eet_identity_close(key); +} + +void * +eet_identity_compute_sha1(const void *data_base, + unsigned int data_length, + int *sha1_length) +{ + void *result; + +#ifdef HAVE_SIGNATURE +# ifdef HAVE_GNUTLS + result = malloc(gcry_md_get_algo_dlen(GCRY_MD_SHA1)); + if (!result) + return NULL; + + gcry_md_hash_buffer(GCRY_MD_SHA1, result, data_base, data_length); + if (sha1_length) + *sha1_length = gcry_md_get_algo_dlen(GCRY_MD_SHA1); + +# else /* ifdef HAVE_GNUTLS */ +# ifdef HAVE_OPENSSL + result = malloc(SHA_DIGEST_LENGTH); + if (!result) + return NULL; + + SHA1(data_base, data_length, result); + if (sha1_length) + *sha1_length = SHA_DIGEST_LENGTH; + +# else /* ifdef HAVE_OPENSSL */ + result = NULL; +# endif /* ifdef HAVE_OPENSSL */ +# endif /* ifdef HAVE_GNUTLS */ +#else /* ifdef HAVE_SIGNATURE */ + data_base = NULL; + data_length = 0; + sha1_length = NULL; + result = NULL; +#endif /* ifdef HAVE_SIGNATURE */ + + return result; +} + +Eet_Error +eet_identity_sign(FILE *fp, + Eet_Key *key) +{ +#ifdef HAVE_SIGNATURE + Eet_Error err = EET_ERROR_NONE; + struct stat st_buf; + void *data; + int fd; + int head[3]; + unsigned char *sign = NULL; + unsigned char *cert = NULL; +# ifdef HAVE_GNUTLS + gnutls_datum_t datum = { NULL, 0 }; + size_t sign_len = 0; + size_t cert_len = 0; +#ifdef EET_USE_NEW_PRIVKEY_SIGN_DATA + gnutls_datum_t signum = { NULL, 0 }; + gnutls_privkey_t privkey; +#endif +# else /* ifdef HAVE_GNUTLS */ + EVP_MD_CTX md_ctx; + unsigned int sign_len = 0; + int cert_len = 0; +# endif /* ifdef HAVE_GNUTLS */ + + /* A few check and flush pending write. */ + if (!fp || !key || !key->certificate || !key->private_key) + return EET_ERROR_BAD_OBJECT; + + /* Get the file size. */ + fd = fileno(fp); + if (fd < 0) + return EET_ERROR_BAD_OBJECT; + + if (fstat(fd, &st_buf) < 0) + return EET_ERROR_MMAP_FAILED; + + /* let's make mmap safe and just get 0 pages for IO erro */ + eina_mmap_safety_enabled_set(EINA_TRUE); + + /* Map the file in memory. */ + data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (data == MAP_FAILED) + return EET_ERROR_MMAP_FAILED; + +# ifdef HAVE_GNUTLS + datum.data = data; + datum.size = st_buf.st_size; + + /* Get the signature length */ +#ifdef EET_USE_NEW_PRIVKEY_SIGN_DATA + if (gnutls_privkey_init(&privkey) < 0) + { + err = EET_ERROR_SIGNATURE_FAILED; + goto on_error; + } + + if (gnutls_privkey_import_x509(privkey, key->private_key, 0) < 0) + { + err = EET_ERROR_SIGNATURE_FAILED; + goto on_error; + } + + if (gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0, &datum, &signum) < 0) + { + err = EET_ERROR_SIGNATURE_FAILED; + goto on_error; + } + + sign = signum.data; + sign_len = signum.size; +#else + if (gnutls_x509_privkey_sign_data(key->private_key, GNUTLS_DIG_SHA1, 0, + &datum, sign, &sign_len) && + !sign_len) + { + err = EET_ERROR_SIGNATURE_FAILED; + goto on_error; + } + + /* Get the signature */ + sign = malloc(sign_len); + if (!sign || + gnutls_x509_privkey_sign_data(key->private_key, GNUTLS_DIG_SHA1, 0, + &datum, + sign, &sign_len)) + { + if (!sign) + err = EET_ERROR_OUT_OF_MEMORY; + else + err = EET_ERROR_SIGNATURE_FAILED; + + goto on_error; + } +#endif + + /* Get the certificate length */ + if (gnutls_x509_crt_export(key->certificate, GNUTLS_X509_FMT_DER, cert, + &cert_len) && + !cert_len) + { + err = EET_ERROR_SIGNATURE_FAILED; + goto on_error; + } + + /* Get the certificate */ + cert = malloc(cert_len); + if (!cert || + gnutls_x509_crt_export(key->certificate, GNUTLS_X509_FMT_DER, cert, + &cert_len)) + { + if (!cert) + err = EET_ERROR_OUT_OF_MEMORY; + else + err = EET_ERROR_SIGNATURE_FAILED; + + goto on_error; + } + +# else /* ifdef HAVE_GNUTLS */ + sign_len = EVP_PKEY_size(key->private_key); + sign = malloc(sign_len); + if (!sign) + { + err = EET_ERROR_OUT_OF_MEMORY; + goto on_error; + } + + /* Do the signature. */ + EVP_SignInit(&md_ctx, EVP_sha1()); + EVP_SignUpdate(&md_ctx, data, st_buf.st_size); + err = EVP_SignFinal(&md_ctx, + sign, + (unsigned int *)&sign_len, + key->private_key); + if (err != 1) + { + ERR_print_errors_fp(stdout); + err = EET_ERROR_SIGNATURE_FAILED; + goto on_error; + } + + /* Give me the der (binary form for X509). */ + cert_len = i2d_X509(key->certificate, &cert); + if (cert_len < 0) + { + ERR_print_errors_fp(stdout); + err = EET_ERROR_X509_ENCODING_FAILED; + goto on_error; + } + +# endif /* ifdef HAVE_GNUTLS */ + /* Append the signature at the end of the file. */ + head[0] = (int)htonl ((unsigned int)EET_MAGIC_SIGN); + head[1] = (int)htonl ((unsigned int)sign_len); + head[2] = (int)htonl ((unsigned int)cert_len); + + if (fwrite(head, sizeof(head), 1, fp) != 1) + { + err = EET_ERROR_WRITE_ERROR; + goto on_error; + } + + if (fwrite(sign, sign_len, 1, fp) != 1) + { + err = EET_ERROR_WRITE_ERROR; + goto on_error; + } + + if (fwrite(cert, cert_len, 1, fp) != 1) + { + err = EET_ERROR_WRITE_ERROR; + goto on_error; + } + +on_error: +# ifdef HAVE_GNUTLS + if (cert) + free(cert); + +# else /* ifdef HAVE_GNUTLS */ + if (cert) + OPENSSL_free(cert); + +# endif /* ifdef HAVE_GNUTLS */ + if (sign) + free(sign); + + munmap(data, st_buf.st_size); + return err; +#else /* ifdef HAVE_SIGNATURE */ + fp = NULL; + key = NULL; + return EET_ERROR_NOT_IMPLEMENTED; +#endif /* ifdef HAVE_SIGNATURE */ +} + +const void * +eet_identity_check(const void *data_base, + unsigned int data_length, + void **sha1, + int *sha1_length, + const void *signature_base, + unsigned int signature_length, + const void **raw_signature_base, + unsigned int *raw_signature_length, + int *x509_length) +{ +#ifdef HAVE_SIGNATURE + const int *header = signature_base; + const unsigned char *sign; + const unsigned char *cert_der; + int sign_len; + int cert_len; + int magic; + + /* At least the header size */ + if (signature_length < sizeof(int) * 3) + return NULL; + + /* Get the header */ + magic = ntohl(header[0]); + sign_len = ntohl(header[1]); + cert_len = ntohl(header[2]); + + /* Verify the header */ + if (magic != EET_MAGIC_SIGN) + return NULL; + + if (sign_len + cert_len + sizeof(int) * 3 > signature_length) + return NULL; + + /* Update the signature and certificate pointer */ + sign = (unsigned char *)signature_base + sizeof(int) * 3; + cert_der = sign + sign_len; + +# ifdef HAVE_GNUTLS + gnutls_x509_crt_t cert; + gnutls_datum_t datum; + gnutls_datum_t signature; +# if EET_USE_NEW_GNUTLS_API +# if EET_USE_NEW_PUBKEY_VERIFY_HASH + gnutls_pubkey_t pubkey; + gnutls_digest_algorithm_t hash_algo; +# endif + unsigned char *hash; + gcry_md_hd_t md; + int err; +# endif /* if EET_USE_NEW_GNUTLS_API */ + + /* Create an understanding certificate structure for gnutls */ + datum.data = (void *)cert_der; + datum.size = cert_len; + gnutls_x509_crt_init(&cert); + gnutls_x509_crt_import(cert, &datum, GNUTLS_X509_FMT_DER); + + signature.data = (void *)sign; + signature.size = sign_len; + + /* Verify the signature */ +# if EET_USE_NEW_GNUTLS_API + /* + I am waiting for my patch being accepted in GnuTLS release. + But we now have a way to prevent double computation of SHA1. + */ + err = gcry_md_open (&md, GCRY_MD_SHA1, 0); + if (err < 0) + return NULL; + + gcry_md_write(md, data_base, data_length); + + hash = gcry_md_read(md, GCRY_MD_SHA1); + if (!hash) + goto on_error; + + datum.size = gcry_md_get_algo_dlen(GCRY_MD_SHA1); + datum.data = hash; + +# ifdef EET_USE_NEW_PUBKEY_VERIFY_HASH + if (gnutls_pubkey_init(&pubkey) < 0) + goto on_error; + + if (gnutls_pubkey_import_x509(pubkey, cert, 0) < 0) + goto on_error; + + if (gnutls_pubkey_get_verify_algorithm(pubkey, &signature, &hash_algo) < 0) + goto on_error; + + if (gnutls_pubkey_verify_hash(pubkey, 0, &datum, &signature) < 0) + goto on_error; +# else + if (!gnutls_x509_crt_verify_hash(cert, 0, &datum, &signature)) + goto on_error; +# endif + + if (sha1) + { + *sha1 = malloc(datum.size); + if (!*sha1) goto on_error; + + memcpy(*sha1, hash, datum.size); + *sha1_length = datum.size; + } + + gcry_md_close(md); +# else /* if EET_USE_NEW_GNUTLS_API */ + datum.data = (void *)data_base; + datum.size = data_length; + + if (!gnutls_x509_crt_verify_data(cert, 0, &datum, &signature)) + return NULL; + + if (sha1) + { + *sha1 = NULL; + *sha1_length = -1; + } + +# endif /* if EET_USE_NEW_GNUTLS_API */ + gnutls_x509_crt_deinit(cert); + +# else /* ifdef HAVE_GNUTLS */ + const unsigned char *tmp; + EVP_PKEY *pkey; + X509 *x509; + EVP_MD_CTX md_ctx; + int err; + + /* Strange but d2i_X509 seems to put 0 all over the place. */ + tmp = alloca(cert_len); + memcpy((char *)tmp, cert_der, cert_len); + x509 = d2i_X509(NULL, &tmp, cert_len); + if (!x509) + return NULL; + + /* Get public key - eay */ + pkey = X509_get_pubkey(x509); + if (!pkey) + { + X509_free(x509); + return NULL; + } + + /* Verify the signature */ + EVP_VerifyInit(&md_ctx, EVP_sha1()); + EVP_VerifyUpdate(&md_ctx, data_base, data_length); + err = EVP_VerifyFinal(&md_ctx, sign, sign_len, pkey); + + X509_free(x509); + EVP_PKEY_free(pkey); + + if (sha1) + { + *sha1 = NULL; + *sha1_length = -1; + } + + if (err != 1) + return NULL; + +# endif /* ifdef HAVE_GNUTLS */ + if (x509_length) + *x509_length = cert_len; + + if (raw_signature_base) + *raw_signature_base = sign; + + if (raw_signature_length) + *raw_signature_length = sign_len; + + return cert_der; +# ifdef HAVE_GNUTLS +# if EET_USE_NEW_GNUTLS_API + on_error: + gcry_md_close(md); + return NULL; +# endif +# endif +#else /* ifdef HAVE_SIGNATURE */ + data_base = NULL; + data_length = 0; + sha1 = NULL; + sha1_length = NULL; + signature_base = NULL; + signature_length = 0; + raw_signature_base = NULL; + raw_signature_length = NULL; + x509_length = NULL; + return NULL; +#endif /* ifdef HAVE_SIGNATURE */ +} + +EAPI void +eet_identity_certificate_print(const unsigned char *certificate, + int der_length, + FILE *out) +{ +#ifdef HAVE_SIGNATURE + if (!certificate || !out || der_length <= 0) + { + ERR("No certificate provided."); + return; + } + +# ifdef HAVE_GNUTLS + gnutls_datum_t datum; + gnutls_x509_crt_t cert; + + /* Create an understanding certificate structure for gnutls */ + datum.data = (void *)certificate; + datum.size = der_length; + if (gnutls_x509_crt_init(&cert)) + goto on_error; + + if (gnutls_x509_crt_import(cert, &datum, GNUTLS_X509_FMT_DER)) + goto on_error; + + /* Pretty print the certificate */ + datum.data = NULL; + datum.size = 0; + if (gnutls_x509_crt_print(cert, GNUTLS_X509_CRT_FULL, &datum)) + goto on_error; + + INF("Public certificate :"); + INF("%s", datum.data); + +on_error: + if (datum.data) + gnutls_free(datum.data); + + gnutls_x509_crt_deinit(cert); +# else /* ifdef HAVE_GNUTLS */ + const unsigned char *tmp; + X509 *x509; + + /* Strange but d2i_X509 seems to put 0 all over the place. */ + tmp = alloca(der_length); + memcpy((char *)tmp, certificate, der_length); + x509 = d2i_X509(NULL, &tmp, der_length); + if (!x509) + { + INF("Not a valid certificate."); + return; + } + + INF("Public certificate :"); + X509_print_fp(out, x509); + + X509_free(x509); +# endif /* ifdef HAVE_GNUTLS */ +#else /* ifdef HAVE_SIGNATURE */ + certificate = NULL; + der_length = 0; + out = NULL; + ERR("You need to compile signature support in EET."); +#endif /* ifdef HAVE_SIGNATURE */ +} + +Eet_Error +eet_cipher(const void *data, + unsigned int size, + const char *key, + unsigned int length, + void **result, + unsigned int *result_length) +{ +#ifdef HAVE_CIPHER + /* Cipher declarations */ + unsigned int *ret = NULL; + unsigned char iv[MAX_IV_LEN]; + unsigned char ik[MAX_KEY_LEN]; + unsigned char key_material[MAX_IV_LEN + MAX_KEY_LEN]; + unsigned int salt; + unsigned int tmp = 0; + int crypted_length; + int opened = 0; +# ifdef HAVE_GNUTLS + /* Gcrypt declarations */ + gcry_error_t err = 0; + gcry_cipher_hd_t cipher; +# else /* ifdef HAVE_GNUTLS */ + /* Openssl declarations*/ + EVP_CIPHER_CTX ctx; + unsigned int *buffer = NULL; + int tmp_len; +# endif /* ifdef HAVE_GNUTLS */ + +# ifdef HAVE_GNUTLS + /* Gcrypt salt generation */ + gcry_create_nonce((unsigned char *)&salt, sizeof(salt)); +# else /* ifdef HAVE_GNUTLS */ + /* Openssl salt generation */ + if (!RAND_bytes((unsigned char *)&salt, sizeof (unsigned int))) + return EET_ERROR_PRNG_NOT_SEEDED; + +# endif /* ifdef HAVE_GNUTLS */ + + eet_pbkdf2_sha1(key, + length, + (unsigned char *)&salt, + sizeof(unsigned int), + 2048, + key_material, + MAX_KEY_LEN + MAX_IV_LEN); + + memcpy(iv, key_material, MAX_IV_LEN); + memcpy(ik, key_material + MAX_IV_LEN, MAX_KEY_LEN); + + memset(key_material, 0, sizeof (key_material)); + + crypted_length = ((((size + sizeof (unsigned int)) >> 5) + 1) << 5); + ret = malloc(crypted_length + sizeof(unsigned int)); + if (!ret) + { + memset(iv, 0, sizeof (iv)); + memset(ik, 0, sizeof (ik)); + memset(&salt, 0, sizeof (salt)); + return EET_ERROR_OUT_OF_MEMORY; + } + + *ret = salt; + memset(&salt, 0, sizeof (salt)); + tmp = htonl(size); + +# ifdef HAVE_GNUTLS + *(ret + 1) = tmp; + memcpy(ret + 2, data, size); + + /* Gcrypt create the corresponding cipher + AES with a 256 bit key, Cipher Block Chaining mode */ + err = gcry_cipher_open(&cipher, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0); + if (err) + goto on_error; + + opened = 1; + err = gcry_cipher_setiv(cipher, iv, MAX_IV_LEN); + if (err) + goto on_error; + + err = gcry_cipher_setkey(cipher, ik, MAX_KEY_LEN); + if (err) + goto on_error; + + memset(iv, 0, sizeof (iv)); + memset(ik, 0, sizeof (ik)); + + /* Gcrypt encrypt */ + err = gcry_cipher_encrypt(cipher, + (unsigned char *)(ret + 1), + crypted_length, + NULL, + 0); + if (err) + goto on_error; + + /* Gcrypt close the cipher */ + gcry_cipher_close(cipher); +# else /* ifdef HAVE_GNUTLS */ + buffer = malloc(crypted_length); + if (!buffer) goto on_error; + *buffer = tmp; + + memcpy(buffer + 1, data, size); + + /* Openssl create the corresponding cipher + AES with a 256 bit key, Cipher Block Chaining mode */ + EVP_CIPHER_CTX_init(&ctx); + if (!EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, ik, iv)) + goto on_error; + + opened = 1; + + memset(iv, 0, sizeof (iv)); + memset(ik, 0, sizeof (ik)); + + /* Openssl encrypt */ + if (!EVP_EncryptUpdate(&ctx, (unsigned char *)(ret + 1), &tmp_len, + (unsigned char *)buffer, + size + sizeof(unsigned int))) + goto on_error; + + /* Openssl close the cipher */ + if (!EVP_EncryptFinal_ex(&ctx, ((unsigned char *)(ret + 1)) + tmp_len, + &tmp_len)) + goto on_error; + + EVP_CIPHER_CTX_cleanup(&ctx); + free(buffer); +# endif /* ifdef HAVE_GNUTLS */ + + /* Set return values */ + if (result_length) + *result_length = crypted_length + sizeof(unsigned int); + + if (result) + *result = ret; + else + free(ret); + + return EET_ERROR_NONE; + +on_error: + memset(iv, 0, sizeof (iv)); + memset(ik, 0, sizeof (ik)); + +# ifdef HAVE_GNUTLS + /* Gcrypt error */ + if (opened) + gcry_cipher_close(cipher); + +# else /* ifdef HAVE_GNUTLS */ + /* Openssl error */ + if (opened) + EVP_CIPHER_CTX_cleanup(&ctx); + + free(buffer); + +# endif /* ifdef HAVE_GNUTLS */ + /* General error */ + free(ret); + if (result) + *result = NULL; + + if (result_length) + *result_length = 0; + + return EET_ERROR_ENCRYPT_FAILED; +#else /* ifdef HAVE_CIPHER */ + /* Cipher not supported */ + (void)data; + (void)size; + (void)key; + (void)length; + (void)result; + (void)result_length; + return EET_ERROR_NOT_IMPLEMENTED; +#endif /* ifdef HAVE_CIPHER */ +} + +Eet_Error +eet_decipher(const void *data, + unsigned int size, + const char *key, + unsigned int length, + void **result, + unsigned int *result_length) +{ +#ifdef HAVE_CIPHER + const unsigned int *over = data; + unsigned int *ret = NULL; + unsigned char ik[MAX_KEY_LEN]; + unsigned char iv[MAX_IV_LEN]; + unsigned char key_material[MAX_KEY_LEN + MAX_IV_LEN]; + unsigned int salt; + int tmp_len; + int tmp = 0; + + /* At least the salt and an AES block */ + if (size < sizeof(unsigned int) + 16) + return EET_ERROR_BAD_OBJECT; + + /* Get the salt */ + salt = *over; + + /* Generate the iv and the key with the salt */ + eet_pbkdf2_sha1(key, length, (unsigned char *)&salt, + sizeof(unsigned int), 2048, key_material, + MAX_KEY_LEN + MAX_IV_LEN); + + memcpy(iv, key_material, MAX_IV_LEN); + memcpy(ik, key_material + MAX_IV_LEN, MAX_KEY_LEN); + + memset(key_material, 0, sizeof (key_material)); + memset(&salt, 0, sizeof (salt)); + + /* Align to AES block size if size is not align */ + tmp_len = size - sizeof (unsigned int); + if ((tmp_len & 0x1F) != 0) + goto on_error; + + ret = malloc(tmp_len); + if (!ret) + goto on_error; + +# ifdef HAVE_GNUTLS + gcry_error_t err = 0; + gcry_cipher_hd_t cipher; + + /* Gcrypt create the corresponding cipher */ + err = gcry_cipher_open(&cipher, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0); + if (err) + return EET_ERROR_DECRYPT_FAILED; + + err = gcry_cipher_setiv(cipher, iv, MAX_IV_LEN); + if (err) + goto on_error; + + err = gcry_cipher_setkey(cipher, ik, MAX_KEY_LEN); + if (err) + goto on_error; + + memset(iv, 0, sizeof (iv)); + memset(ik, 0, sizeof (ik)); + + /* Gcrypt decrypt */ + err = gcry_cipher_decrypt(cipher, ret, tmp_len, + ((unsigned int *)data) + 1, tmp_len); + if (err) + goto on_error; + + /* Gcrypt close the cipher */ + gcry_cipher_close(cipher); + +# else /* ifdef HAVE_GNUTLS */ + EVP_CIPHER_CTX ctx; + int opened = 0; + + /* Openssl create the corresponding cipher */ + EVP_CIPHER_CTX_init(&ctx); + opened = 1; + + if (!EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, ik, iv)) + goto on_error; + + memset(iv, 0, sizeof (iv)); + memset(ik, 0, sizeof (ik)); + + /* Openssl decrypt */ + if (!EVP_DecryptUpdate(&ctx, (unsigned char *)ret, &tmp, + (unsigned char *)(over + 1), tmp_len)) + goto on_error; + + /* Openssl close the cipher*/ + EVP_CIPHER_CTX_cleanup(&ctx); +# endif /* ifdef HAVE_GNUTLS */ + /* Get the decrypted data size */ + tmp = *ret; + tmp = ntohl(tmp); + if (tmp > tmp_len || tmp <= 0) + goto on_error; + + /* Update the return values */ + if (result_length) + *result_length = tmp; + + if (result) + { + *result = NULL; + *result = malloc(tmp); + if (!*result) + goto on_error; + + memcpy(*result, ret + 1, tmp); + } + + free(ret); + + return EET_ERROR_NONE; + +on_error: + memset(iv, 0, sizeof (iv)); + memset(ik, 0, sizeof (ik)); + +# ifdef HAVE_GNUTLS +# else + if (opened) + EVP_CIPHER_CTX_cleanup(&ctx); + +# endif /* ifdef HAVE_GNUTLS */ + if (result) + *result = NULL; + + if (result_length) + *result_length = 0; + + if (ret) + free(ret); + + return EET_ERROR_DECRYPT_FAILED; +#else /* ifdef HAVE_CIPHER */ + (void)data; + (void)size; + (void)key; + (void)length; + (void)result; + (void)result_length; + return EET_ERROR_NOT_IMPLEMENTED; +#endif /* ifdef HAVE_CIPHER */ +} + +#ifdef HAVE_CIPHER +# ifdef HAVE_GNUTLS +static Eet_Error +eet_hmac_sha1(const void *key, + size_t key_len, + const void *data, + size_t data_len, + unsigned char *res) +{ + size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1); + gcry_md_hd_t mdh; + unsigned char *hash; + gpg_error_t err; + + err = gcry_md_open(&mdh, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); + if (err != GPG_ERR_NO_ERROR) + return 1; + + err = gcry_md_setkey(mdh, key, key_len); + if (err != GPG_ERR_NO_ERROR) + { + gcry_md_close(mdh); + return 1; + } + + gcry_md_write(mdh, data, data_len); + + hash = gcry_md_read(mdh, GCRY_MD_SHA1); + if (!hash) + { + gcry_md_close(mdh); + return 1; + } + + memcpy(res, hash, hlen); + + gcry_md_close(mdh); + + return 0; +} + +# endif /* ifdef HAVE_GNUTLS */ + +static Eet_Error +eet_pbkdf2_sha1(const char *key, + int key_len, + const unsigned char *salt, + unsigned int salt_len, + int iter, + unsigned char *res, + int res_len) +{ + unsigned char digest[20]; + unsigned char tab[4]; + unsigned char *p = res; + unsigned char *buf; + unsigned long i; + int digest_len = 20; + int len = res_len; + int tmp_len; + int j, k; +# ifdef HAVE_GNUTLS +# else + HMAC_CTX hctx; +# endif /* ifdef HAVE_GNUTLS */ + + buf = alloca(salt_len + 4); + if (!buf) + return 1; + + for (i = 1; len; len -= tmp_len, p += tmp_len, i++) + { + if (len > digest_len) + tmp_len = digest_len; + else + tmp_len = len; + + tab[0] = (unsigned char)(i & 0xff000000) >> 24; + tab[1] = (unsigned char)(i & 0x00ff0000) >> 16; + tab[2] = (unsigned char)(i & 0x0000ff00) >> 8; + tab[3] = (unsigned char)(i & 0x000000ff) >> 0; + +# ifdef HAVE_GNUTLS + memcpy(buf, salt, salt_len); + memcpy(buf + salt_len, tab, 4); + eet_hmac_sha1(key, key_len, buf, salt_len + 4, digest); +# else /* ifdef HAVE_GNUTLS */ + HMAC_Init(&hctx, key, key_len, EVP_sha1()); + HMAC_Update(&hctx, salt, salt_len); + HMAC_Update(&hctx, tab, 4); + HMAC_Final(&hctx, digest, NULL); +# endif /* ifdef HAVE_GNUTLS */ + memcpy(p, digest, tmp_len); + + for (j = 1; j < iter; j++) + { +# ifdef HAVE_GNUTLS + eet_hmac_sha1(key, key_len, digest, 20, digest); +# else /* ifdef HAVE_GNUTLS */ + HMAC(EVP_sha1(), key, key_len, digest, 20, digest, NULL); +# endif /* ifdef HAVE_GNUTLS */ + for (k = 0; k < tmp_len; k++) + p[k] ^= digest[k]; + } + } + +# ifdef HAVE_GNUTLS +# else + HMAC_cleanup(&hctx); +# endif /* ifdef HAVE_GNUTLS */ + return 0; +} + +#endif /* ifdef HAVE_CIPHER */ diff --git a/src/lib/eet_connection.c b/src/lib/eet_connection.c new file mode 100644 index 0000000..a192d4e --- /dev/null +++ b/src/lib/eet_connection.c @@ -0,0 +1,232 @@ +#ifdef HAVE_CONFIG_H +# include +#endif /* ifdef HAVE_CONFIG_H */ + +#ifdef HAVE_ALLOCA_H +# include +#elif defined __GNUC__ +# define alloca __builtin_alloca +#elif defined _AIX +# define alloca __alloca +#elif defined _MSC_VER +# include +# define alloca _alloca +#else /* ifdef HAVE_ALLOCA_H */ +# include +# ifdef __cplusplus +extern "C" +# endif /* ifdef __cplusplus */ +void *alloca(size_t); +#endif /* ifdef HAVE_ALLOCA_H */ + +#include +#include + +#ifdef HAVE_NETINET_IN_H +# include +#endif /* ifdef HAVE_NETINET_IN_H */ + +#ifdef _WIN32 +# include +#endif /* ifdef _WIN32 */ + +#include + +#include "Eet.h" +#include "Eet_private.h" + +/* max message size: 1Mb - raised from original 64Kb */ +#define MAX_MSG_SIZE (1024 * 1024) +#define MAGIC_EET_DATA_PACKET 0x4270ACE1 + +struct _Eet_Connection +{ + Eet_Read_Cb *eet_read_cb; + Eet_Write_Cb *eet_write_cb; + void *user_data; + + size_t allocated; + size_t size; + size_t received; + + void *buffer; +}; + +EAPI Eet_Connection * +eet_connection_new(Eet_Read_Cb *eet_read_cb, + Eet_Write_Cb *eet_write_cb, + const void *user_data) +{ + Eet_Connection *conn; + + if ((!eet_read_cb) || (!eet_write_cb)) return NULL; + + conn = calloc(1, sizeof (Eet_Connection)); + if (!conn) return NULL; + conn->eet_read_cb = eet_read_cb; + conn->eet_write_cb = eet_write_cb; + conn->user_data = (void *)user_data; + return conn; +} + +EAPI int +eet_connection_received(Eet_Connection *conn, + const void *data, + size_t size) +{ + if ((!conn) || (!data) || (!size)) return size; + do + { + size_t copy_size; + + if (conn->size == 0) + { + const int *msg; + size_t packet_size; + + if (size < (sizeof(int) * 2)) break; + + msg = data; + /* Check the magic */ + if (ntohl(msg[0]) != MAGIC_EET_DATA_PACKET) break; + + packet_size = ntohl(msg[1]); + /* Message should always be under MAX_MSG_SIZE */ + if (packet_size > MAX_MSG_SIZE) break; + + data = (void *)(msg + 2); + size -= sizeof(int) * 2; + if ((size_t)packet_size <= size) + { + /* Not a partial receive, go the quick way. */ + if (!conn->eet_read_cb(data, packet_size, conn->user_data)) + break; + + data = (void *)((char *)data + packet_size); + size -= packet_size; + conn->received = 0; + continue; + } + conn->size = packet_size; + if (conn->allocated < conn->size) + { + void *tmp; + + tmp = realloc(conn->buffer, conn->size); + if (!tmp) break; + conn->buffer = tmp; + conn->allocated = conn->size; + } + } + + /* Partial receive */ + copy_size = + (conn->size - conn->received >= + size) ? size : conn->size - conn->received; + memcpy((char *)conn->buffer + conn->received, data, copy_size); + + conn->received += copy_size; + data = (void *)((char *)data + copy_size); + size -= copy_size; + + if (conn->received == conn->size) + { + size_t data_size; + + data_size = conn->size; + conn->size = 0; + conn->received = 0; + /* Completed a packet. */ + if (!conn->eet_read_cb(conn->buffer, data_size, conn->user_data)) + { + /* Something goes wrong. Stop now. */ + size += data_size; + break; + } + } + } + while (size > 0); + + return size; +} + +static Eina_Bool +_eet_connection_raw_send(Eet_Connection *conn, + void *data, + int data_size) +{ + int *message; + + /* Message should always be under MAX_MSG_SIZE */ + if (data_size > MAX_MSG_SIZE) return EINA_FALSE; + message = alloca(data_size + (sizeof(int) * 2)); + message[0] = htonl(MAGIC_EET_DATA_PACKET); + message[1] = htonl(data_size); + memcpy(message + 2, data, data_size); + conn->eet_write_cb(message, + data_size + (sizeof(int) * 2), + conn->user_data); + return EINA_TRUE; +} + +EAPI Eina_Bool +eet_connection_empty(Eet_Connection *conn) +{ + return conn->size ? EINA_FALSE : EINA_TRUE; +} + +EAPI Eina_Bool +eet_connection_send(Eet_Connection *conn, + Eet_Data_Descriptor *edd, + const void *data_in, + const char *cipher_key) +{ + void *flat_data; + int data_size; + Eina_Bool ret = EINA_FALSE; + + EINA_SAFETY_ON_NULL_RETURN_VAL(conn, EINA_FALSE); + + flat_data = eet_data_descriptor_encode_cipher(edd, + data_in, + cipher_key, + &data_size); + if (!flat_data) return EINA_FALSE; + if (_eet_connection_raw_send(conn, flat_data, data_size)) ret = EINA_TRUE; + free(flat_data); + return ret; +} + +EAPI Eina_Bool +eet_connection_node_send(Eet_Connection *conn, + Eet_Node *node, + const char *cipher_key) +{ + void *data; + int data_size; + Eina_Bool ret = EINA_FALSE; + + EINA_SAFETY_ON_NULL_RETURN_VAL(conn, EINA_FALSE); + + data = eet_data_node_encode_cipher(node, cipher_key, &data_size); + if (!data) return EINA_FALSE; + if (_eet_connection_raw_send(conn, data, data_size)) + ret = EINA_TRUE; + free(data); + return ret; +} + +EAPI void * +eet_connection_close(Eet_Connection *conn, + Eina_Bool *on_going) +{ + void *user_data; + + if (!conn) return NULL; + if (on_going) *on_going = conn->received == 0 ? EINA_FALSE : EINA_TRUE; + user_data = conn->user_data; + free(conn->buffer); + free(conn); + return user_data; +} + diff --git a/src/lib/eet_data.c b/src/lib/eet_data.c index f15f923..f995353 100644 --- a/src/lib/eet_data.c +++ b/src/lib/eet_data.c @@ -1,16 +1,6 @@ -/* - * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 - */ - #ifdef HAVE_CONFIG_H # include -#endif - -#if HAVE___ATTRIBUTE__ -#define __UNUSED__ __attribute__((unused)) -#else -#define __UNUSED__ -#endif +#endif /* ifdef HAVE_CONFIG_H */ #include #include @@ -20,11 +10,13 @@ #ifdef HAVE_NETINET_IN_H # include -#endif +#endif /* ifdef HAVE_NETINET_IN_H */ -#if defined(_WIN32) && ! defined(__CEGCC__) +#ifdef _WIN32 # include -#endif +#endif /* ifdef _WIN32 */ + +#include #include "Eet.h" #include "Eet_private.h" @@ -69,13 +61,16 @@ /*---*/ -typedef struct _Eet_Data_Element Eet_Data_Element; -typedef struct _Eet_Data_Basic_Type_Codec Eet_Data_Basic_Type_Codec; -typedef struct _Eet_Data_Group_Type_Codec Eet_Data_Group_Type_Codec; -typedef struct _Eet_Data_Chunk Eet_Data_Chunk; -typedef struct _Eet_Data_Stream Eet_Data_Stream; -typedef struct _Eet_Data_Descriptor_Hash Eet_Data_Descriptor_Hash; -typedef struct _Eet_Data_Encode_Hash_Info Eet_Data_Encode_Hash_Info; +typedef struct _Eet_Data_Element Eet_Data_Element; +typedef struct _Eet_Data_Basic_Type_Codec Eet_Data_Basic_Type_Codec; +typedef struct _Eet_Data_Group_Type_Codec Eet_Data_Group_Type_Codec; +typedef struct _Eet_Data_Chunk Eet_Data_Chunk; +typedef struct _Eet_Data_Stream Eet_Data_Stream; +typedef struct _Eet_Data_Descriptor_Hash Eet_Data_Descriptor_Hash; +typedef struct _Eet_Data_Encode_Hash_Info Eet_Data_Encode_Hash_Info; +typedef struct _Eet_Free Eet_Free; +typedef struct _Eet_Free_Context Eet_Free_Context; +typedef struct _Eet_Variant_Unknow Eet_Variant_Unknow; /*---*/ @@ -87,25 +82,41 @@ struct _Eet_Data_Basic_Type_Codec { int size; const char *name; - int (*get) (const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest); - void *(*put) (Eet_Dictionary *ed, const void *src, int *size_ret); + int (*get)(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); + void * (*put)(Eet_Dictionary *ed, const void *src, int *size_ret); }; struct _Eet_Data_Group_Type_Codec { - int (*get) (const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data_in, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size); - void (*put) (Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in); + int (*get)(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type, + int group_type, + void *data_in, + char **p, + int *size); + void (*put)(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in); }; struct _Eet_Data_Chunk { - char *name; - int len; - int size; - int hash; - void *data; - unsigned char type; - unsigned char group_type; + const char *name; + int len; + int size; + int hash; + void *data; + unsigned char type; + unsigned char group_type; }; struct _Eet_Data_Stream @@ -126,29 +137,45 @@ struct _Eet_Data_Descriptor const char *name; const Eet_Dictionary *ed; int size; - struct { - void *(*mem_alloc) (size_t size); - void (*mem_free) (void *mem); - char *(*str_alloc) (const char *str); - char *(*str_direct_alloc) (const char *str); - void (*str_free) (const char *str); - void (*str_direct_free) (const char *str); - void *(*list_next) (void *l); - void *(*list_append) (void *l, void *d); - void *(*list_data) (void *l); - void *(*list_free) (void *l); - void (*hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt); - void *(*hash_add) (void *h, const char *k, void *d); - void (*hash_free) (void *h); + struct + { + void * (*mem_alloc)(size_t size); + void (*mem_free)(void *mem); + char * (*str_alloc)(const char *str); + char * (*str_direct_alloc)(const char *str); + void (*str_free)(const char *str); + void (*str_direct_free)(const char *str); + void * (*list_next)(void *l); + void * (*list_append)(void *l, void *d); + void * (*list_data)(void *l); + void * (*list_free)(void *l); + void (*hash_foreach)(void *h, + int (*func)(void *h, + const char *k, + void *dt, + void *fdt), + void *fdt); + void * (*hash_add)(void *h, const char *k, void *d); + void (*hash_free)(void *h); + const char *(*type_get)(const void *data, Eina_Bool *unknow); + Eina_Bool (*type_set)(const char *type, + void *data, + Eina_Bool unknow); + void * (*array_alloc)(size_t size); + void (*array_free)(void *mem); } func; - struct { - int num; - Eet_Data_Element *set; - struct { - int size; - Eet_Data_Descriptor_Hash *buckets; + struct + { + int num; + Eet_Data_Element *set; + struct + { + int size; + Eet_Data_Descriptor_Hash *buckets; } hash; } elements; + + Eina_Bool unified_type : 1; // char *strings; // int strings_len; }; @@ -159,136 +186,454 @@ struct _Eet_Data_Element const char *counter_name; const char *directory_name_ptr; Eet_Data_Descriptor *subtype; - int offset; /* offset in bytes from the base element */ - int count; /* number of elements for a fixed array */ - int counter_offset; /* for a variable array we need the offset of the count variable */ - unsigned char type; /* EET_T_XXX */ - unsigned char group_type; /* EET_G_XXX */ + int offset; /* offset in bytes from the base element */ + int count; /* number of elements for a fixed array */ + int counter_offset; /* for a variable array we need the offset of the count variable */ + unsigned char type; /* EET_T_XXX */ + unsigned char group_type; /* EET_G_XXX */ }; struct _Eet_Data_Encode_Hash_Info { - Eet_Data_Stream *ds; - Eet_Data_Element *ede; - Eet_Dictionary *ed; + Eet_Data_Stream *ds; + Eet_Data_Element *ede; + Eet_Dictionary *ed; +}; + +#define EET_FREE_COUNT 256 +struct _Eet_Free +{ + int ref; + Eina_Array list[EET_FREE_COUNT]; +}; + +struct _Eet_Free_Context +{ + Eet_Free freelist; + Eet_Free freelist_array; + Eet_Free freelist_list; + Eet_Free freelist_hash; + Eet_Free freelist_str; + Eet_Free freelist_direct_str; +}; + +struct _Eet_Variant_Unknow +{ + EINA_MAGIC + + int size; + char data[1]; }; /*---*/ -static int eet_data_get_char(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest); -static void *eet_data_put_char(Eet_Dictionary *ed, const void *src, int *size_ret); -static int eet_data_get_short(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest); -static void *eet_data_put_short(Eet_Dictionary *ed, const void *src, int *size_ret); -static int eet_data_get_int(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest); -static void *eet_data_put_int(Eet_Dictionary *ed, const void *src, int *size_ret); -static int eet_data_get_long_long(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest); -static void *eet_data_put_long_long(Eet_Dictionary *ed, const void *src, int *size_ret); -static int eet_data_get_float(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest); -static void *eet_data_put_float(Eet_Dictionary *ed, const void *src, int *size_ret); -static int eet_data_get_double(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest); -static void *eet_data_put_double(Eet_Dictionary *ed, const void *src, int *size_ret); -static int eet_data_get_string(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest); -static void *eet_data_put_string(Eet_Dictionary *ed, const void *src, int *size_ret); -static int eet_data_get_istring(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest); -static void *eet_data_put_istring(Eet_Dictionary *ed, const void *src, int *size_ret); - -static int eet_data_get_type(const Eet_Dictionary *ed, int type, const void *src, const void *src_end, void *dest); -static void *eet_data_put_type(Eet_Dictionary *ed, int type, const void *src, int *size_ret); - -static int eet_data_get_unknown(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data_in, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size); -static void eet_data_put_unknown(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in); -static void eet_data_put_array(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in); -static int eet_data_get_array(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size); -static int eet_data_get_list(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data_in, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size); -static void eet_data_put_list(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in); -static void eet_data_put_hash(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in); -static int eet_data_get_hash(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size); - -static void eet_data_chunk_get(const Eet_Dictionary *ed, Eet_Data_Chunk *chnk, const void *src, int size); -static Eet_Data_Chunk *eet_data_chunk_new(void *data, int size, const char *name, int type, int group_type); -static void eet_data_chunk_free(Eet_Data_Chunk *chnk); - -static Eet_Data_Stream *eet_data_stream_new(void); -static void eet_data_stream_write(Eet_Data_Stream *ds, const void *data, int size); -static void eet_data_stream_free(Eet_Data_Stream *ds); - -static void eet_data_chunk_put(Eet_Dictionary *ed, Eet_Data_Chunk *chnk, Eet_Data_Stream *ds); - -static int eet_data_descriptor_encode_hash_cb(void *hash, const char *key, void *hdata, void *fdata); -static void *_eet_data_descriptor_encode(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, const void *data_in, int *size_ret); -static void *_eet_data_descriptor_decode(const Eet_Dictionary *ed, - Eet_Data_Descriptor *edd, - const void *data_in, - int size_in, - int level, - void (*dumpfunc) (void *data, const char *str), - void *dumpdata); +static void + eet_free_context_init(Eet_Free_Context *context); +static void + eet_free_context_shutdown(Eet_Free_Context *context); + +static int +eet_data_get_char(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_char(Eet_Dictionary *ed, + const void *src, + int *size_ret); +static int +eet_data_get_short(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_short(Eet_Dictionary *ed, + const void *src, + int *size_ret); +static inline int +eet_data_get_int(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_int(Eet_Dictionary *ed, + const void *src, + int *size_ret); +static int +eet_data_get_long_long(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_long_long(Eet_Dictionary *ed, + const void *src, + int *size_ret); +static int +eet_data_get_float(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_float(Eet_Dictionary *ed, + const void *src, + int *size_ret); +static int +eet_data_get_double(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_double(Eet_Dictionary *ed, + const void *src, + int *size_ret); +static int +eet_data_get_f32p32(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_f32p32(Eet_Dictionary *ed, + const void *src, + int *size_ret); +static int +eet_data_get_f16p16(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_f16p16(Eet_Dictionary *ed, + const void *src, + int *size_ret); +static int +eet_data_get_f8p24(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_f8p24(Eet_Dictionary *ed, + const void *src, + int *size_ret); +static inline int +eet_data_get_string(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_string(Eet_Dictionary *ed, + const void *src, + int *size_ret); +static int +eet_data_get_istring(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_istring(Eet_Dictionary *ed, + const void *src, + int *size_ret); +static int +eet_data_get_null(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_null(Eet_Dictionary *ed, + const void *src, + int *size_ret); + +static int +eet_data_get_type(const Eet_Dictionary *ed, + int type, + const void *src, + const void *src_end, + void *dest); +static void * +eet_data_put_type(Eet_Dictionary *ed, + int type, + const void *src, + int *size_ret); + +static Eet_Node * +eet_data_node_simple_type(int type, + const char *name, + void *dd); + +static int +eet_data_get_unknown(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type, + int group_type, + void *data_in, + char **p, + int *size); +static void +eet_data_put_unknown(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in); +static void +eet_data_put_array(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in); +static int +eet_data_get_array(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type, + int group_type, + void *data, + char **p, + int *size); +static int +eet_data_get_list(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type, + int group_type, + void *data_in, + char **p, + int *size); +static void +eet_data_put_list(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in); +static void +eet_data_put_hash(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in); +static int +eet_data_get_hash(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type, + int group_type, + void *data, + char **p, + int *size); +static void +eet_data_put_union(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in); +static int +eet_data_get_union(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type, + int group_type, + void *data, + char **p, + int *size); +static void +eet_data_put_variant(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in); +static int +eet_data_get_variant(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type, + int group_type, + void *data, + char **p, + int *size); + +static void +eet_data_chunk_get(const Eet_Dictionary *ed, + Eet_Data_Chunk *chnk, + const void *src, + int size); +static Eet_Data_Chunk * +eet_data_chunk_new(void *data, + int size, + const char *name, + int type, + int group_type); +static void +eet_data_chunk_free(Eet_Data_Chunk *chnk); + +static Eet_Data_Stream * + eet_data_stream_new(void); +static void + eet_data_stream_write(Eet_Data_Stream *ds, + const void *data, + int size); +static void +eet_data_stream_free(Eet_Data_Stream *ds); + +static void +eet_data_chunk_put(Eet_Dictionary *ed, + Eet_Data_Chunk *chnk, + Eet_Data_Stream *ds); + +static int +eet_data_descriptor_encode_hash_cb(void *hash, + const char *key, + void *hdata, + void *fdata); +static void *_eet_data_descriptor_encode(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + const void *data_in, + int *size_ret); +static void *_eet_data_descriptor_decode(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + const void *data_in, + int size_in, + void *data_out, + int size_out); /*---*/ static const Eet_Data_Basic_Type_Codec eet_basic_codec[] = { - {sizeof(char), "char", eet_data_get_char, eet_data_put_char }, - {sizeof(short), "short", eet_data_get_short, eet_data_put_short }, - {sizeof(int), "int", eet_data_get_int, eet_data_put_int }, - {sizeof(long long), "long_long", eet_data_get_long_long, eet_data_put_long_long}, - {sizeof(float), "float", eet_data_get_float, eet_data_put_float }, - {sizeof(double), "double", eet_data_get_double, eet_data_put_double }, - {sizeof(char), "uchar", eet_data_get_char, eet_data_put_char }, - {sizeof(short), "ushort", eet_data_get_short, eet_data_put_short }, - {sizeof(int), "uint", eet_data_get_int, eet_data_put_int }, - {sizeof(long long), "ulong_long", eet_data_get_long_long, eet_data_put_long_long}, - {sizeof(char *), "string", eet_data_get_string, eet_data_put_string }, - {sizeof(char *), "inlined", eet_data_get_istring, eet_data_put_istring } + {sizeof(char), "char", eet_data_get_char, eet_data_put_char }, + {sizeof(short), "short", eet_data_get_short, eet_data_put_short }, + {sizeof(int), "int", eet_data_get_int, eet_data_put_int }, + {sizeof(long long), "long_long", eet_data_get_long_long, eet_data_put_long_long}, + {sizeof(float), "float", eet_data_get_float, eet_data_put_float }, + {sizeof(double), "double", eet_data_get_double, eet_data_put_double }, + {sizeof(char), "uchar", eet_data_get_char, eet_data_put_char }, + {sizeof(short), "ushort", eet_data_get_short, eet_data_put_short }, + {sizeof(int), "uint", eet_data_get_int, eet_data_put_int }, + {sizeof(long long), "ulong_long", eet_data_get_long_long, eet_data_put_long_long}, + {sizeof(char *), "string", eet_data_get_string, eet_data_put_string }, + {sizeof(char *), "inlined", eet_data_get_istring, eet_data_put_istring }, + {sizeof(void *), "NULL", eet_data_get_null, eet_data_put_null }, + {sizeof(Eina_F32p32), "f32p32", eet_data_get_f32p32, eet_data_put_f32p32 }, + {sizeof(Eina_F16p16), "f16p16", eet_data_get_f16p16, eet_data_put_f16p16 }, + {sizeof(Eina_F8p24), "f8p24", eet_data_get_f8p24, eet_data_put_f8p24 } }; static const Eet_Data_Group_Type_Codec eet_group_codec[] = { - { eet_data_get_unknown, eet_data_put_unknown }, - { eet_data_get_array, eet_data_put_array }, - { eet_data_get_array, eet_data_put_array }, - { eet_data_get_list, eet_data_put_list }, - { eet_data_get_hash, eet_data_put_hash } + { eet_data_get_unknown, eet_data_put_unknown }, + { eet_data_get_array, eet_data_put_array }, + { eet_data_get_array, eet_data_put_array }, + { eet_data_get_list, eet_data_put_list }, + { eet_data_get_hash, eet_data_put_hash }, + { eet_data_get_union, eet_data_put_union }, + { eet_data_get_variant, eet_data_put_variant } }; -static int words_bigendian = -1; +static int _eet_data_words_bigendian = -1; /*---*/ -#define SWAP64(x) (x) = \ - ((((unsigned long long)(x) & 0x00000000000000ffULL ) << 56) |\ - (((unsigned long long)(x) & 0x000000000000ff00ULL ) << 40) |\ - (((unsigned long long)(x) & 0x0000000000ff0000ULL ) << 24) |\ - (((unsigned long long)(x) & 0x00000000ff000000ULL ) << 8) |\ - (((unsigned long long)(x) & 0x000000ff00000000ULL ) >> 8) |\ - (((unsigned long long)(x) & 0x0000ff0000000000ULL ) >> 24) |\ - (((unsigned long long)(x) & 0x00ff000000000000ULL ) >> 40) |\ - (((unsigned long long)(x) & 0xff00000000000000ULL ) >> 56)) -#define SWAP32(x) (x) = \ - ((((int)(x) & 0x000000ff ) << 24) |\ - (((int)(x) & 0x0000ff00 ) << 8) |\ - (((int)(x) & 0x00ff0000 ) >> 8) |\ - (((int)(x) & 0xff000000 ) >> 24)) -#define SWAP16(x) (x) = \ - ((((short)(x) & 0x00ff ) << 8) |\ - (((short)(x) & 0xff00 ) >> 8)) +#define SWAP64(x) (x) = \ + ((((unsigned long long)(x) & 0x00000000000000ffULL) << 56) | \ + (((unsigned long long)(x) & 0x000000000000ff00ULL) << 40) | \ + (((unsigned long long)(x) & 0x0000000000ff0000ULL) << 24) | \ + (((unsigned long long)(x) & 0x00000000ff000000ULL) << 8) | \ + (((unsigned long long)(x) & 0x000000ff00000000ULL) >> 8) | \ + (((unsigned long long)(x) & 0x0000ff0000000000ULL) >> 24) | \ + (((unsigned long long)(x) & 0x00ff000000000000ULL) >> 40) | \ + (((unsigned long long)(x) & 0xff00000000000000ULL) >> 56)) +#define SWAP32(x) (x) = \ + ((((int)(x) & 0x000000ff) << 24) | \ + (((int)(x) & 0x0000ff00) << 8) | \ + (((int)(x) & 0x00ff0000) >> 8) | \ + (((int)(x) & 0xff000000) >> 24)) +#define SWAP16(x) (x) = \ + ((((short)(x) & 0x00ff) << 8) | \ + (((short)(x) & 0xff00) >> 8)) + +#ifdef CONV8 +# undef CONV8 +#endif /* ifdef CONV8 */ +#ifdef CONV16 +# undef CONV16 +#endif /* ifdef CONV16 */ +#ifdef CONV32 +# undef CONV32 +#endif /* ifdef CONV32 */ +#ifdef CONV64 +# undef CONV64 +#endif /* ifdef CONV64 */ #define CONV8(x) -#define CONV16(x) {if (words_bigendian) SWAP16(x);} -#define CONV32(x) {if (words_bigendian) SWAP32(x);} -#define CONV64(x) {if (words_bigendian) SWAP64(x);} - -#define IS_SIMPLE_TYPE(Type) (Type > EET_T_UNKNOW && Type < EET_T_LAST) - +#define CONV16(x) {if (_eet_data_words_bigendian) {SWAP16(x); }} +#define CONV32(x) {if (_eet_data_words_bigendian) {SWAP32(x); }} +#define CONV64(x) {if (_eet_data_words_bigendian) {SWAP64(x); }} + +#define IS_SIMPLE_TYPE(Type) (Type > EET_T_UNKNOW && Type < EET_T_LAST) +#define IS_POINTER_TYPE(Type) (Type >= EET_T_STRING && Type <= EET_T_NULL) + +#define POINTER_TYPE_DECODE(Context, \ + Ed, \ + Edd, \ + Ede, \ + Echnk, \ + Type, \ + Data, \ + P, \ + Size, \ + Label) \ + do { \ + int ___r; \ + ___r = eet_data_get_unknown(Context, \ + Ed, \ + Edd, Ede, \ + Echnk, \ + Type, EET_G_UNKNOWN, \ + Data, P, Size); \ + if (!___r) { goto Label; } \ + } while (0) + +#define STRUCT_TYPE_DECODE(Data_Ret, Context, Ed, Ede, Data, Size, SubSize, Label) \ + do { \ + Data_Ret = _eet_data_descriptor_decode(Context, \ + Ed, \ + Ede, \ + Data, \ + Size, \ + SubSize > 0 ? Data_Ret : NULL, \ + SubSize); \ + if (!Data_Ret) { goto Label; } \ + } while (0) + +#define EET_I_STRING 1 << 4 +#define EET_I_INLINED_STRING 2 << 4 +#define EET_I_NULL 3 << 4 + +#define EET_MAGIC_VARIANT 0xF1234BC /*---*/ /* CHAR TYPE */ static int -eet_data_get_char(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst) +eet_data_get_char(const Eet_Dictionary *ed __UNUSED__, + const void *src, + const void *src_end, + void *dst) { char *s, *d; - if (((char *)src + sizeof(char)) > (char *)src_end) return -1; + if (((char *)src + sizeof(char)) > (char *)src_end) + return -1; + s = (char *)src; d = (char *)dst; *d = *s; @@ -297,12 +642,16 @@ eet_data_get_char(const Eet_Dictionary *ed __UNUSED__, const void *src, const vo } static void * -eet_data_put_char(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret) +eet_data_put_char(Eet_Dictionary *ed __UNUSED__, + const void *src, + int *size_ret) { char *s, *d; d = (char *)malloc(sizeof(char)); - if (!d) return NULL; + if (!d) + return NULL; + s = (char *)src; *d = *s; CONV8(*d); @@ -312,11 +661,16 @@ eet_data_put_char(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret) /* SHORT TYPE */ static int -eet_data_get_short(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst) +eet_data_get_short(const Eet_Dictionary *ed __UNUSED__, + const void *src, + const void *src_end, + void *dst) { short *d; - if (((char *)src + sizeof(short)) > (char *)src_end) return -1; + if (((char *)src + sizeof(short)) > (char *)src_end) + return -1; + memcpy(dst, src, sizeof(short)); d = (short *)dst; CONV16(*d); @@ -324,12 +678,16 @@ eet_data_get_short(const Eet_Dictionary *ed __UNUSED__, const void *src, const v } static void * -eet_data_put_short(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret) +eet_data_put_short(Eet_Dictionary *ed __UNUSED__, + const void *src, + int *size_ret) { short *s, *d; d = (short *)malloc(sizeof(short)); - if (!d) return NULL; + if (!d) + return NULL; + s = (short *)src; *d = *s; CONV16(*d); @@ -338,12 +696,17 @@ eet_data_put_short(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret } /* INT TYPE */ -static int -eet_data_get_int(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst) +static inline int +eet_data_get_int(const Eet_Dictionary *ed __UNUSED__, + const void *src, + const void *src_end, + void *dst) { int *d; - if (((char *)src + sizeof(int)) > (char *)src_end) return -1; + if (((char *)src + sizeof(int)) > (char *)src_end) + return -1; + memcpy(dst, src, sizeof(int)); d = (int *)dst; CONV32(*d); @@ -351,12 +714,16 @@ eet_data_get_int(const Eet_Dictionary *ed __UNUSED__, const void *src, const voi } static void * -eet_data_put_int(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret) +eet_data_put_int(Eet_Dictionary *ed __UNUSED__, + const void *src, + int *size_ret) { int *s, *d; d = (int *)malloc(sizeof(int)); - if (!d) return NULL; + if (!d) + return NULL; + s = (int *)src; *d = *s; CONV32(*d); @@ -366,11 +733,16 @@ eet_data_put_int(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret) /* LONG LONG TYPE */ static int -eet_data_get_long_long(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst) +eet_data_get_long_long(const Eet_Dictionary *ed __UNUSED__, + const void *src, + const void *src_end, + void *dst) { unsigned long long *d; - if (((char *)src + sizeof(unsigned long long)) > (char *)src_end) return -1; + if (((char *)src + sizeof(unsigned long long)) > (char *)src_end) + return -1; + memcpy(dst, src, sizeof(unsigned long long)); d = (unsigned long long *)dst; CONV64(*d); @@ -378,12 +750,16 @@ eet_data_get_long_long(const Eet_Dictionary *ed __UNUSED__, const void *src, con } static void * -eet_data_put_long_long(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret) +eet_data_put_long_long(Eet_Dictionary *ed __UNUSED__, + const void *src, + int *size_ret) { unsigned long long *s, *d; d = (unsigned long long *)malloc(sizeof(unsigned long long)); - if (!d) return NULL; + if (!d) + return NULL; + s = (unsigned long long *)src; *d = *s; CONV64(*d); @@ -392,23 +768,29 @@ eet_data_put_long_long(Eet_Dictionary *ed __UNUSED__, const void *src, int *size } /* STRING TYPE */ -static int -eet_data_get_string_hash(const Eet_Dictionary *ed, const void *src, const void *src_end) +static inline int +eet_data_get_string_hash(const Eet_Dictionary *ed, + const void *src, + const void *src_end) { if (ed) { - int index; + int idx; - if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1; + if (eet_data_get_int(ed, src, src_end, &idx) < 0) + return -1; - return eet_dictionary_string_get_hash(ed, index); + return eet_dictionary_string_get_hash(ed, idx); } return -1; } -static int -eet_data_get_string(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst) +static inline int +eet_data_get_string(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dst) { char *s, **d; @@ -416,21 +798,22 @@ eet_data_get_string(const Eet_Dictionary *ed, const void *src, const void *src_e if (ed) { - const char *str; - int index; + const char *str; + int idx; - if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1; + if (eet_data_get_int(ed, src, src_end, &idx) < 0) + return -1; - str = eet_dictionary_string_get_char(ed, index); - if (str == NULL) + str = eet_dictionary_string_get_char(ed, idx); + if (!str) return -1; - *d = (char *) str; - return eet_dictionary_string_get_size(ed, index); + *d = (char *)str; + return eet_dictionary_string_get_size(ed, idx); } s = (char *)src; - if (s == NULL) + if (!s) { *d = NULL; return 0; @@ -441,30 +824,38 @@ eet_data_get_string(const Eet_Dictionary *ed, const void *src, const void *src_e } static void * -eet_data_put_string(Eet_Dictionary *ed, const void *src, int *size_ret) +eet_data_put_string(Eet_Dictionary *ed, + const void *src, + int *size_ret) { char *s, *d; int len; if (ed) { - const char *str; - int index; + const char *str; + int idx; - str = *((const char **) src); - if (!str) return NULL; + str = *((const char **)src); + if (!str) + return NULL; - index = eet_dictionary_string_add(ed, str); - if (index == -1) return NULL; + idx = eet_dictionary_string_add(ed, str); + if (idx == -1) + return NULL; - return eet_data_put_int(ed, &index, size_ret); + return eet_data_put_int(ed, &idx, size_ret); } s = (char *)(*((char **)src)); - if (!s) return NULL; + if (!s) + return NULL; + len = strlen(s); d = malloc(len + 1); - if (!d) return NULL; + if (!d) + return NULL; + memcpy(d, s, len + 1); *size_ret = len + 1; return d; @@ -472,17 +863,46 @@ eet_data_put_string(Eet_Dictionary *ed, const void *src, int *size_ret) /* ALWAYS INLINED STRING TYPE */ static int -eet_data_get_istring(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst) +eet_data_get_istring(const Eet_Dictionary *ed __UNUSED__, + const void *src, + const void *src_end, + void *dst) { return eet_data_get_string(NULL, src, src_end, dst); } static void * -eet_data_put_istring(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret) +eet_data_put_istring(Eet_Dictionary *ed __UNUSED__, + const void *src, + int *size_ret) { return eet_data_put_string(NULL, src, size_ret); } +/* ALWAYS NULL TYPE */ +static int +eet_data_get_null(const Eet_Dictionary *ed __UNUSED__, + const void *src __UNUSED__, + const void *src_end __UNUSED__, + void *dst) +{ + char **d; + + d = (char **)dst; + + *d = NULL; + return 1; +} + +static void * +eet_data_put_null(Eet_Dictionary *ed __UNUSED__, + const void *src __UNUSED__, + int *size_ret) +{ + *size_ret = 0; + return NULL; +} + /** * Fast lookups of simple doubles/floats. * @@ -490,167 +910,334 @@ eet_data_put_istring(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_r * values, but have a so simple math that is almost as fast. */ static inline int -_eet_data_float_cache_get(const char *s, int len, float *d) +_eet_data_float_cache_get(const char *s, + int len, + float *d) { /* fast handle of simple case 0xMp+E*/ - if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p')) - { - int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0'); - int exponent = (s[5] - '0'); + if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p')) + { + int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0'); + int exponent = (s[5] - '0'); - if (s[4] == '+') *d = (float)(mantisse << exponent); - else *d = (float)mantisse / (float)(1 << exponent); + if (s[4] == '+') + *d = (float)(mantisse << exponent); + else + *d = (float)mantisse / (float)(1 << exponent); - return 1; - } - return 0; + return 1; + } + + return 0; } static inline int -_eet_data_double_cache_get(const char *s, int len, double *d) +_eet_data_double_cache_get(const char *s, + int len, + double *d) { /* fast handle of simple case 0xMp+E*/ - if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p')) - { - int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0'); - int exponent = (s[5] - '0'); + if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p')) + { + int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0'); + int exponent = (s[5] - '0'); - if (s[4] == '+') *d = (double)(mantisse << exponent); - else *d = (double)mantisse / (double)(1 << exponent); + if (s[4] == '+') + *d = (double)(mantisse << exponent); + else + *d = (double)mantisse / (double)(1 << exponent); - return 1; - } - return 0; + return 1; + } + + return 0; } /* FLOAT TYPE */ static int -eet_data_get_float(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst) +eet_data_get_float(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dst) { - float *d; - int index; + float *d; + int idx; - d = (float *) dst; + d = (float *)dst; if (!ed) { - const char *s, *p; - long long mantisse; - long exponent; - int len; + const char *s, *p; + long long mantisse; + long exponent; + int len; s = (const char *)src; p = s; len = 0; - while ((p < (const char *)src_end) && (*p != 0)) {len++; p++;} + while ((p < (const char *)src_end) && (*p != 0)) {len++; p++; } + + if (_eet_data_float_cache_get(s, len, d) != 0) + return len + 1; - if (_eet_data_float_cache_get(s, len, d) != 0) return len + 1; + if (eina_convert_atod(s, len, &mantisse, &exponent) == EINA_FALSE) + return -1; - _eet_string_to_double_convert(s, &mantisse, &exponent); *d = (float)ldexp((double)mantisse, exponent); return len + 1; } - if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1; + if (eet_data_get_int(ed, src, src_end, &idx) < 0) + return -1; - if (!eet_dictionary_string_get_float(ed, index, d)) + if (!eet_dictionary_string_get_float(ed, idx, d)) return -1; + return 1; } static void * -eet_data_put_float(Eet_Dictionary *ed, const void *src, int *size_ret) +eet_data_put_float(Eet_Dictionary *ed, + const void *src, + int *size_ret) { - char buf[128]; - int index; + char buf[128]; + int idx; - _eet_double_to_string_convert(buf, (double)(*(float *)src)); + eina_convert_dtoa((double)(*(float *)src), buf); if (!ed) { - char *d; - int len; + char *d; + int len; len = strlen(buf); d = malloc(len + 1); - if (!d) return NULL; - memcpy(d, buf, len + 1); + if (!d) + return NULL; + + memcpy(d, buf, len + 1); *size_ret = len + 1; return d; } - index = eet_dictionary_string_add(ed, buf); - if (index == -1) return NULL; + idx = eet_dictionary_string_add(ed, buf); + if (idx == -1) + return NULL; - return eet_data_put_int(ed, &index, size_ret); + return eet_data_put_int(ed, &idx, size_ret); } /* DOUBLE TYPE */ static int -eet_data_get_double(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst) +eet_data_get_double(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dst) { - double *d; - int index; + double *d; + int idx; - d = (double *) dst; + d = (double *)dst; if (!ed) { - const char *s, *p; - long long mantisse = 0; - long exponent = 0; - int len; + const char *s, *p; + long long mantisse = 0; + long exponent = 0; + int len; - s = (const char *) src; + s = (const char *)src; p = s; len = 0; - while ((p < (const char *)src_end) && (*p != 0)) {len++; p++;} + while ((p < (const char *)src_end) && (*p != 0)) {len++; p++; } + + if (_eet_data_double_cache_get(s, len, d) != 0) + return len + 1; - if (_eet_data_double_cache_get(s, len, d) != 0) return len + 1; + if (eina_convert_atod(s, len, &mantisse, &exponent) == EINA_FALSE) + return -1; - _eet_string_to_double_convert(s, &mantisse, &exponent); - *d = ldexp((double) mantisse, exponent); + *d = ldexp((double)mantisse, exponent); return len + 1; } - if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1; + if (eet_data_get_int(ed, src, src_end, &idx) < 0) + return -1; + + if (!eet_dictionary_string_get_double(ed, idx, d)) + return -1; + + return 1; +} + +static void * +eet_data_put_double(Eet_Dictionary *ed, + const void *src, + int *size_ret) +{ + char buf[128]; + int idx; + + eina_convert_dtoa((double)(*(double *)src), buf); + + if (!ed) + { + char *d; + int len; + + len = strlen(buf); + d = malloc(len + 1); + if (!d) + return NULL; + + memcpy(d, buf, len + 1); + *size_ret = len + 1; + + return d; + } + + idx = eet_dictionary_string_add(ed, buf); + if (idx == -1) + return NULL; + + return eet_data_put_int(ed, &idx, size_ret); +} + +static int +eet_data_get_f32p32(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dst) +{ + Eina_F32p32 *fp; + int idx; + + fp = (Eina_F32p32 *)dst; + + if (!ed) + { + const char *s, *p; + int len; + + s = (const char *)src; + p = s; + len = 0; + while ((p < (const char *)src_end) && (*p != 0)) { len++; p++; } + + if (!(eina_convert_atofp(s, len, fp))) + return -1; + + return 1; + } + + if (eet_data_get_int(ed, src, src_end, &idx) < 0) + return -1; - if (!eet_dictionary_string_get_double(ed, index, d)) + if (!eet_dictionary_string_get_fp(ed, idx, fp)) return -1; + return 1; } static void * -eet_data_put_double(Eet_Dictionary *ed, const void *src, int *size_ret) +eet_data_put_f32p32(Eet_Dictionary *ed, + const void *src, + int *size_ret) { - char buf[128]; - int index; + char buf[128]; + int idx; - _eet_double_to_string_convert(buf, (double)(*(double *)src)); + eina_convert_fptoa((Eina_F32p32)(*(Eina_F32p32 *)src), buf); if (!ed) { - char *d; - int len; + char *d; + int len; len = strlen(buf); d = malloc(len + 1); - if (!d) return NULL; - memcpy(d, buf, len + 1); + if (!d) + return NULL; + + memcpy(d, buf, len + 1); *size_ret = len + 1; return d; } - index = eet_dictionary_string_add(ed, buf); - if (index == -1) return NULL; + idx = eet_dictionary_string_add(ed, buf); + if (idx == -1) + return NULL; + + return eet_data_put_int(ed, &idx, size_ret); +} + +static int +eet_data_get_f16p16(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dst) +{ + Eina_F32p32 tmp; + Eina_F16p16 *fp; + + fp = (Eina_F16p16 *)dst; + + if (eet_data_get_f32p32(ed, src, src_end, &tmp) < 0) + return -1; + + *fp = eina_f32p32_to_f16p16(tmp); + return 1; +} + +static void * +eet_data_put_f16p16(Eet_Dictionary *ed, + const void *src, + int *size_ret) +{ + Eina_F32p32 tmp; - return eet_data_put_int(ed, &index, size_ret); + tmp = eina_f16p16_to_f32p32((Eina_F16p16)(*(Eina_F16p16 *)src)); + return eet_data_put_f32p32(ed, &tmp, size_ret); } static int -eet_data_get_type(const Eet_Dictionary *ed, int type, const void *src, const void *src_end, void *dest) +eet_data_get_f8p24(const Eet_Dictionary *ed, + const void *src, + const void *src_end, + void *dst) +{ + Eina_F32p32 tmp; + Eina_F8p24 *fp; + + fp = (Eina_F8p24 *)dst; + + if (eet_data_get_f32p32(ed, src, src_end, &tmp) < 0) + return -1; + + *fp = eina_f32p32_to_f8p24(tmp); + return 1; +} + +static void * +eet_data_put_f8p24(Eet_Dictionary *ed, + const void *src, + int *size_ret) +{ + Eina_F32p32 tmp; + + tmp = eina_f8p24_to_f32p32((Eina_F8p24)(*(Eina_F8p24 *)src)); + return eet_data_put_f32p32(ed, &tmp, size_ret); +} + +static inline int +eet_data_get_type(const Eet_Dictionary *ed, + int type, + const void *src, + const void *src_end, + void *dest) { int ret; @@ -658,8 +1245,11 @@ eet_data_get_type(const Eet_Dictionary *ed, int type, const void *src, const voi return ret; } -static void * -eet_data_put_type(Eet_Dictionary *ed, int type, const void *src, int *size_ret) +static inline void * +eet_data_put_type(Eet_Dictionary *ed, + int type, + const void *src, + int *size_ret) { void *ret; @@ -667,6 +1257,43 @@ eet_data_put_type(Eet_Dictionary *ed, int type, const void *src, int *size_ret) return ret; } +static inline Eina_Bool +eet_data_type_match(int type1, + int type2) +{ + if (type1 == type2) + return EINA_TRUE; + + /* Note: All floating point type are equivalent and could be read + without problem by any other floating point getter. */ + switch (type1) + { + case EET_T_FLOAT: + case EET_T_DOUBLE: + case EET_T_F32P32: + case EET_T_F16P16: + case EET_T_F8P24: + switch (type2) + { + case EET_T_FLOAT: + case EET_T_DOUBLE: + case EET_T_F32P32: + case EET_T_F16P16: + case EET_T_F8P24: + return EINA_TRUE; + + default: + break; + } /* switch */ + break; + + default: + break; + } + + return EINA_FALSE; +} + /* chunk format... * * char[4] = "CHnK"; // untyped data ... or @@ -680,61 +1307,78 @@ eet_data_put_type(Eet_Dictionary *ed, int type, const void *src, int *size_ret) * */ -static void -eet_data_chunk_get(const Eet_Dictionary *ed, Eet_Data_Chunk *chnk, - const void *src, int size) +static inline void +eet_data_chunk_get(const Eet_Dictionary *ed, + Eet_Data_Chunk *chnk, + const void *src, + int size) { const char *s; int ret1, ret2; - if (!src) return; - if (size <= 8) return; + if (!src) + return; + + if (size <= 8) + return; - if (!chnk) return; + if (!chnk) + return; s = src; if (s[2] == 'K') { - if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'K')) - { - return; - } - chnk->type = (unsigned char)(s[3]); - if (chnk->type > EET_T_LAST) - { - chnk->group_type = chnk->type; - chnk->type = EET_T_UNKNOW; - } - else - chnk->group_type = EET_G_UNKNOWN; - if ((chnk->type >= EET_T_LAST) || - (chnk->group_type >= EET_G_LAST)) - { - chnk->type = 0; - chnk->group_type = 0; - } - } - else - { - if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'n') || (s[3] != 'K')) - { - return; - } + if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'K')) + return; + + chnk->type = (unsigned char)(s[3]); + if (chnk->type >= EET_I_LIMIT) + { + chnk->group_type = + ((chnk->type - EET_I_LIMIT) & 0xF) + EET_G_UNKNOWN; + switch ((chnk->type - EET_I_LIMIT) & 0xF0) + { +#define EET_UNMATCH_TYPE(Type) \ +case EET_I_ ## Type: chnk->type = EET_T_ ## Type; break; + + EET_UNMATCH_TYPE(STRING); + EET_UNMATCH_TYPE(INLINED_STRING); + EET_UNMATCH_TYPE(NULL); + + default: + return; + } + } + else if (chnk->type > EET_T_LAST) + { + chnk->group_type = chnk->type; + chnk->type = EET_T_UNKNOW; + } + else + chnk->group_type = EET_G_UNKNOWN; + if ((chnk->type >= EET_T_LAST) || + (chnk->group_type >= + EET_G_LAST)) + { + chnk->type = 0; + chnk->group_type = 0; + } } + else if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'n') || (s[3] != 'K')) + return; + ret1 = eet_data_get_type(ed, EET_T_INT, (s + 4), (s + size), &(chnk->size)); + if (ret1 <= 0) - { - return; - } + return; + if ((chnk->size < 0) || ((chnk->size + 8) > size)) - { - return; - } + return; + ret2 = eet_data_get_type(ed, EET_T_STRING, (s + 8), (s + size), &(chnk->name)); + if (ret2 <= 0) - { - return; - } + return; chnk->len = ret2; @@ -755,16 +1399,30 @@ eet_data_chunk_get(const Eet_Dictionary *ed, Eet_Data_Chunk *chnk, return; } -static Eet_Data_Chunk * -eet_data_chunk_new(void *data, int size, const char *name, int type, int group_type) +static inline Eet_Data_Chunk * +eet_data_chunk_new(void *data, + int size, + const char *name, + int type, + int group_type) { Eet_Data_Chunk *chnk; - if (!name) return NULL; + if (!name) + return NULL; + chnk = calloc(1, sizeof(Eet_Data_Chunk)); - if (!chnk) return NULL; + if (!chnk) + return NULL; - chnk->name = strdup(name); + /* Note: Another security, so older eet library could read file + saved with fixed point value. */ + if (type == EET_T_F32P32 + || type == EET_T_F16P16 + || type == EET_T_F8P24) + type = EET_T_DOUBLE; + + chnk->name = name; chnk->len = strlen(name) + 1; chnk->size = size; chnk->data = data; @@ -773,71 +1431,114 @@ eet_data_chunk_new(void *data, int size, const char *name, int type, int group_t return chnk; } -static void +static inline void eet_data_chunk_free(Eet_Data_Chunk *chnk) { - if (chnk->name) free(chnk->name); free(chnk); } -static Eet_Data_Stream * +static inline Eet_Data_Stream * eet_data_stream_new(void) { Eet_Data_Stream *ds; ds = calloc(1, sizeof(Eet_Data_Stream)); - if (!ds) return NULL; + if (!ds) + return NULL; + return ds; } -static void +static inline void eet_data_stream_free(Eet_Data_Stream *ds) { - if (ds->data) free(ds->data); + if (ds->data) + free(ds->data); + free(ds); } -static void -eet_data_stream_write(Eet_Data_Stream *ds, const void *data, int size) +static inline void +eet_data_stream_flush(Eet_Data_Stream *ds) +{ + free(ds); +} + +static inline void +eet_data_stream_write(Eet_Data_Stream *ds, + const void *data, + int size) { char *p; if ((ds->pos + size) > ds->size) { - ds->data = realloc(ds->data, ds->size + size + 512); - if (!ds->data) - { - ds->pos = 0; - ds->size = 0; - return; - } - ds->size = ds->size + size + 512; + ds->data = realloc(ds->data, ds->size + size + 512); + if (!ds->data) + { + ds->pos = 0; + ds->size = 0; + return; + } + + ds->size = ds->size + size + 512; } + p = ds->data; memcpy(p + ds->pos, data, size); ds->pos += size; } static void -eet_data_chunk_put(Eet_Dictionary *ed, Eet_Data_Chunk *chnk, Eet_Data_Stream *ds) +eet_data_chunk_put(Eet_Dictionary *ed, + Eet_Data_Chunk *chnk, + Eet_Data_Stream *ds) { - int *size; + int *size; void *string; - int s; - int size_ret = 0; - int string_ret = 0; + int s; + int size_ret = 0; + int string_ret = 0; unsigned char buf[4] = "CHK"; - if (!chnk->data) return; + /* disable this check - it will allow empty chunks to be written. this is + * right for corner-cases when y have a struct with empty fields (empty + * strings or empty list ptrs etc.) */ + /* if (!chnk->data && chnk->type != EET_T_NULL) return; */ /* chunk head */ /* eet_data_stream_write(ds, "CHnK", 4);*/ - if (chnk->type != EET_T_UNKNOW) buf[3] = chnk->type; - else buf[3] = chnk->group_type; + if (chnk->type != EET_T_UNKNOW) + { + if (chnk->group_type != EET_G_UNKNOWN) + { + int type = EET_I_LIMIT + chnk->group_type - EET_G_UNKNOWN; + + switch (chnk->type) + { + /* Only make sense with pointer type. */ +#define EET_MATCH_TYPE(Type) \ +case EET_T_ ## Type: type += EET_I_ ## Type; break; + + EET_MATCH_TYPE(STRING); + EET_MATCH_TYPE(INLINED_STRING); + EET_MATCH_TYPE(NULL); + + default: + return; + } + + buf[3] = type; + } + else + buf[3] = chnk->type; + } + else + buf[3] = chnk->group_type; string = eet_data_put_string(ed, &chnk->name, &string_ret); if (!string) - return ; + return; /* size of chunk payload data + name */ s = chnk->size + string_ret; @@ -856,11 +1557,12 @@ eet_data_chunk_put(Eet_Dictionary *ed, Eet_Data_Chunk *chnk, Eet_Data_Stream *ds eet_data_stream_write(ds, string, string_ret); /* write payload */ - eet_data_stream_write(ds, chnk->data, chnk->size); + if (chnk->data) + eet_data_stream_write(ds, chnk->data, chnk->size); - free(string); - on_error: free(size); +on_error: + free(string); } /*---*/ @@ -871,25 +1573,28 @@ _eet_descriptor_hash_new(Eet_Data_Descriptor *edd) int i; edd->elements.hash.size = 1 << 6; - edd->elements.hash.buckets = calloc(1, sizeof(Eet_Data_Descriptor_Hash) * edd->elements.hash.size); + edd->elements.hash.buckets = calloc( + 1, + sizeof(Eet_Data_Descriptor_Hash) * + edd->elements.hash.size); for (i = 0; i < edd->elements.num; i++) { - Eet_Data_Element *ede; - int hash; - - ede = &(edd->elements.set[i]); - hash = _eet_hash_gen((char *) ede->name, 6); - if (!edd->elements.hash.buckets[hash].element) - edd->elements.hash.buckets[hash].element = ede; - else - { - Eet_Data_Descriptor_Hash *bucket; - - bucket = calloc(1, sizeof(Eet_Data_Descriptor_Hash)); - bucket->element = ede; - bucket->next = edd->elements.hash.buckets[hash].next; - edd->elements.hash.buckets[hash].next = bucket; - } + Eet_Data_Element *ede; + int hash; + + ede = &(edd->elements.set[i]); + hash = _eet_hash_gen((char *)ede->name, 6); + if (!edd->elements.hash.buckets[hash].element) + edd->elements.hash.buckets[hash].element = ede; + else + { + Eet_Data_Descriptor_Hash *bucket; + + bucket = calloc(1, sizeof(Eet_Data_Descriptor_Hash)); + bucket->element = ede; + bucket->next = edd->elements.hash.buckets[hash].next; + edd->elements.hash.buckets[hash].next = bucket; + } } } @@ -900,49 +1605,61 @@ _eet_descriptor_hash_free(Eet_Data_Descriptor *edd) for (i = 0; i < edd->elements.hash.size; i++) { - Eet_Data_Descriptor_Hash *bucket, *pbucket; - - bucket = edd->elements.hash.buckets[i].next; - while (bucket) - { - pbucket = bucket; - bucket = bucket->next; - free(pbucket); - } + Eet_Data_Descriptor_Hash *bucket, *pbucket; + + bucket = edd->elements.hash.buckets[i].next; + while (bucket) + { + pbucket = bucket; + bucket = bucket->next; + free(pbucket); + } } - if (edd->elements.hash.buckets) free(edd->elements.hash.buckets); + if (edd->elements.hash.buckets) + free(edd->elements.hash.buckets); } static Eet_Data_Element * -_eet_descriptor_hash_find(Eet_Data_Descriptor *edd, char *name, int hash) +_eet_descriptor_hash_find(Eet_Data_Descriptor *edd, + const char *name, + int hash) { Eet_Data_Descriptor_Hash *bucket; - if (hash < 0) hash = _eet_hash_gen(name, 6); - else hash &= 0x3f; - if (!edd->elements.hash.buckets[hash].element) return NULL; - /* - When we use the dictionnary as a source for chunk name, we will always - have the same pointer in name. It's a good idea to just compare pointer - instead of running strcmp on both string. - */ + if (hash < 0) + hash = _eet_hash_gen(name, 6); + else + hash &= 0x3f; + + if (!edd->elements.hash.buckets[hash].element) + return NULL; /* + When we use the dictionary as a source for chunk name, we will always + have the same pointer in name. It's a good idea to just compare pointer + instead of running strcmp on both string. + */ + if (edd->elements.hash.buckets[hash].element->directory_name_ptr == name) return edd->elements.hash.buckets[hash].element; + if (!strcmp(edd->elements.hash.buckets[hash].element->name, name)) { - edd->elements.hash.buckets[hash].element->directory_name_ptr = name; - return edd->elements.hash.buckets[hash].element; + edd->elements.hash.buckets[hash].element->directory_name_ptr = name; + return edd->elements.hash.buckets[hash].element; } + bucket = edd->elements.hash.buckets[hash].next; while (bucket) { - if (bucket->element->directory_name_ptr == name) return bucket->element; - if (!strcmp(bucket->element->name, name)) - { - bucket->element->directory_name_ptr = name; - return bucket->element; - } - bucket = bucket->next; + if (bucket->element->directory_name_ptr == name) + return bucket->element; + + if (!strcmp(bucket->element->name, name)) + { + bucket->element->directory_name_ptr = name; + return bucket->element; + } + + bucket = bucket->next; } return NULL; } @@ -971,54 +1688,128 @@ _eet_str_free(const char *str) free((char *)str); } +static Eina_Hash * +_eet_eina_hash_add_alloc(Eina_Hash *hash, + const char *key, + void *data) +{ + if (!hash) + hash = eina_hash_string_small_new(NULL); + + if (!hash) + return NULL; + + eina_hash_add(hash, key, data); + return hash; +} + +static Eina_Hash * +_eet_eina_hash_direct_add_alloc(Eina_Hash *hash, + const char *key, + void *data) +{ + if (!hash) + hash = eina_hash_string_small_new(NULL); + + if (!hash) + return NULL; + + eina_hash_direct_add(hash, key, data); + return hash; +} + +static char * +_eet_str_direct_alloc(const char *str) +{ + return (char *)str; +} + +static void +_eet_str_direct_free(const char *str __UNUSED__) +{ +} + +static void +_eet_eina_hash_foreach(void *hash, + Eina_Hash_Foreach cb, + void *fdata) +{ + if (hash) + eina_hash_foreach(hash, cb, fdata); +} + +static void +_eet_eina_hash_free(void *hash) +{ + if (hash) + eina_hash_free(hash); +} + /*---*/ +EAPI Eina_Bool +eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, + /* When we change the structure content in the future, we need to handle old structure type too */ + unsigned int eddc_size, + const char *name, + int size) +{ + if (!eddc || !name || eddc_size != sizeof (Eet_Data_Descriptor_Class)) + return EINA_FALSE; + + eddc->name = name; + eddc->size = size; + eddc->version = EET_DATA_DESCRIPTOR_CLASS_VERSION; + + eddc->func.mem_alloc = _eet_mem_alloc; + eddc->func.mem_free = _eet_mem_free; + eddc->func.str_alloc = (char *(*)(const char *))eina_stringshare_add; + eddc->func.str_free = eina_stringshare_del; + eddc->func.list_next = (void *(*)(void *))eina_list_next; + eddc->func.list_append = (void *(*)(void *, void *))eina_list_append; + eddc->func.list_data = (void *(*)(void *))eina_list_data_get; + eddc->func.list_free = (void *(*)(void *))eina_list_free; + eddc->func.hash_foreach = (void (*)(void *, int (*)(void *, const char *, void *, void *), void *))_eet_eina_hash_foreach; + eddc->func.hash_add = (void *(*)(void *, const char *, void *))_eet_eina_hash_add_alloc; + eddc->func.hash_free = (void (*)(void *))_eet_eina_hash_free; + + /* This will cause an ABI incompatibility */ + eddc->func.array_alloc = _eet_mem_alloc; + eddc->func.array_free = _eet_mem_free; + + return EINA_TRUE; +} -EAPI Eet_Data_Descriptor * -eet_data_descriptor_new(const char *name, - int size, - void *(*func_list_next) (void *l), - void *(*func_list_append) (void *l, void *d), - void *(*func_list_data) (void *l), - void *(*func_list_free) (void *l), - void (*func_hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt), - void *(*func_hash_add) (void *h, const char *k, void *d), - void (*func_hash_free) (void *h)) +EAPI Eina_Bool +eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, + /* When we change the structure content in the future, we need to handle old structure type too */ + unsigned int eddc_size, + const char *name, + int size) { - Eet_Data_Descriptor *edd; + if (!eet_eina_stream_data_descriptor_class_set(eddc, eddc_size, name, size)) + return EINA_FALSE; - if (!name) return NULL; - edd = calloc(1, sizeof(Eet_Data_Descriptor)); - if (!edd) return NULL; + eddc->version = EET_DATA_DESCRIPTOR_CLASS_VERSION; - edd->name = name; - edd->ed = NULL; - edd->size = size; - edd->func.mem_alloc = _eet_mem_alloc; - edd->func.mem_free = _eet_mem_free; - edd->func.str_alloc = _eet_str_alloc; - edd->func.str_direct_alloc = NULL; - edd->func.str_direct_free = NULL; - edd->func.str_free = _eet_str_free; - edd->func.list_next = func_list_next; - edd->func.list_append = func_list_append; - edd->func.list_data = func_list_data; - edd->func.list_free = func_list_free; - edd->func.hash_foreach = func_hash_foreach; - edd->func.hash_add = func_hash_add; - edd->func.hash_free = func_hash_free; - return edd; + eddc->func.hash_add = (void *(*)(void *, const char *, void *))_eet_eina_hash_direct_add_alloc; + eddc->func.str_direct_alloc = _eet_str_direct_alloc; + eddc->func.str_direct_free = _eet_str_direct_free; + + return EINA_TRUE; } -/* new replcement */ -EAPI Eet_Data_Descriptor * -eet_data_descriptor2_new(Eet_Data_Descriptor_Class *eddc) +static Eet_Data_Descriptor * +_eet_data_descriptor_new(const Eet_Data_Descriptor_Class *eddc, + int version) { Eet_Data_Descriptor *edd; - if (!eddc) return NULL; - if (eddc->version < 1) return NULL; - edd = calloc(1, sizeof(Eet_Data_Descriptor)); - if (!edd) return NULL; + if (!eddc) + return NULL; + + edd = calloc(1, sizeof (Eet_Data_Descriptor)); + if (!edd) + return NULL; edd->name = eddc->name; edd->ed = NULL; @@ -1029,12 +1820,16 @@ eet_data_descriptor2_new(Eet_Data_Descriptor_Class *eddc) edd->func.str_free = _eet_str_free; if (eddc->func.mem_alloc) edd->func.mem_alloc = eddc->func.mem_alloc; + if (eddc->func.mem_free) edd->func.mem_free = eddc->func.mem_free; + if (eddc->func.str_alloc) edd->func.str_alloc = eddc->func.str_alloc; + if (eddc->func.str_free) edd->func.str_free = eddc->func.str_free; + edd->func.list_next = eddc->func.list_next; edd->func.list_append = eddc->func.list_append; edd->func.list_data = eddc->func.list_data; @@ -1043,74 +1838,181 @@ eet_data_descriptor2_new(Eet_Data_Descriptor_Class *eddc) edd->func.hash_add = eddc->func.hash_add; edd->func.hash_free = eddc->func.hash_free; + if (eddc->version > 1 && version > 1) + { + edd->func.str_direct_alloc = eddc->func.str_direct_alloc; + edd->func.str_direct_free = eddc->func.str_direct_free; + } + + if (eddc->version > 2) + { + edd->func.type_get = eddc->func.type_get; + edd->func.type_set = eddc->func.type_set; + } + + if (eddc->version > 3) + { + edd->func.array_alloc = eddc->func.array_alloc; + edd->func.array_free = eddc->func.array_free; + } + return edd; } EAPI Eet_Data_Descriptor * -eet_data_descriptor3_new(Eet_Data_Descriptor_Class *eddc) +eet_data_descriptor_new(const char *name, + int size, + Eet_Descriptor_List_Next_Callback func_list_next, + Eet_Descriptor_List_Append_Callback func_list_append, + Eet_Descriptor_List_Data_Callback func_list_data, + Eet_Descriptor_List_Free_Callback func_list_free, + Eet_Descriptor_Hash_Foreach_Callback func_hash_foreach, + Eet_Descriptor_Hash_Add_Callback func_hash_add, + Eet_Descriptor_Hash_Free_Callback func_hash_free) { - Eet_Data_Descriptor *edd; + Eet_Data_Descriptor_Class eddc; - if (!eddc) return NULL; - if (eddc->version < 2) return NULL; - edd = calloc(1, sizeof(Eet_Data_Descriptor)); - if (!edd) return NULL; + if (!name) + return NULL; - edd->name = eddc->name; - edd->ed = NULL; - edd->size = eddc->size; - edd->func.mem_alloc = _eet_mem_alloc; - edd->func.mem_free = _eet_mem_free; - edd->func.str_alloc = _eet_str_alloc; - edd->func.str_free = _eet_str_free; - if (eddc->func.mem_alloc) - edd->func.mem_alloc = eddc->func.mem_alloc; - if (eddc->func.mem_free) - edd->func.mem_free = eddc->func.mem_free; - if (eddc->func.str_alloc) - edd->func.str_alloc = eddc->func.str_alloc; - if (eddc->func.str_free) - edd->func.str_free = eddc->func.str_free; - edd->func.list_next = eddc->func.list_next; - edd->func.list_append = eddc->func.list_append; - edd->func.list_data = eddc->func.list_data; - edd->func.list_free = eddc->func.list_free; - edd->func.hash_foreach = eddc->func.hash_foreach; - edd->func.hash_add = eddc->func.hash_add; - edd->func.hash_free = eddc->func.hash_free; - edd->func.str_direct_alloc = eddc->func.str_direct_alloc; - edd->func.str_direct_free = eddc->func.str_direct_free; + memset(&eddc, 0, sizeof (Eet_Data_Descriptor_Class)); - return edd; + eddc.name = name; + eddc.size = size; + eddc.version = 0; + + eddc.func.list_next = func_list_next; + eddc.func.list_append = func_list_append; + eddc.func.list_data = func_list_data; + eddc.func.list_free = func_list_free; + eddc.func.hash_foreach = func_hash_foreach; + eddc.func.hash_add = func_hash_add; + eddc.func.hash_free = func_hash_free; + + return _eet_data_descriptor_new(&eddc, 0); +} + +EAPI Eet_Data_Descriptor * +eet_data_descriptor2_new(const Eet_Data_Descriptor_Class *eddc) +{ + return _eet_data_descriptor_new(eddc, 1); +} + +EAPI Eet_Data_Descriptor * +eet_data_descriptor3_new(const Eet_Data_Descriptor_Class *eddc) +{ + return _eet_data_descriptor_new(eddc, 2); +} + +EAPI Eet_Data_Descriptor * +eet_data_descriptor_stream_new(const Eet_Data_Descriptor_Class *eddc) +{ + return _eet_data_descriptor_new(eddc, 1); +} + +EAPI Eet_Data_Descriptor * +eet_data_descriptor_file_new(const Eet_Data_Descriptor_Class *eddc) +{ + return _eet_data_descriptor_new(eddc, 2); } EAPI void eet_data_descriptor_free(Eet_Data_Descriptor *edd) { + if (!edd) + return; + _eet_descriptor_hash_free(edd); - if (edd->elements.set) free(edd->elements.set); + if (edd->elements.set) + free(edd->elements.set); + free(edd); } EAPI void eet_data_descriptor_element_add(Eet_Data_Descriptor *edd, - const char *name, - int type, - int group_type, - int offset, - int count, -/* int counter_offset, */ - const char *counter_name /* Useless should go on a major release */, - Eet_Data_Descriptor *subtype) + const char *name, + int type, + int group_type, + int offset, + int count, +/* int counter_offset, */ + const char *counter_name /* FIXME: Useless should go on a major release */, + Eet_Data_Descriptor *subtype) { Eet_Data_Element *ede; - /* int l1, l2, p1, p2, i; - char *ps;*/ + Eet_Data_Element *tmp; + + EINA_SAFETY_ON_NULL_RETURN(edd); + + /* Sanity check to avoid crash later at runtime */ + if (type < EET_T_UNKNOW || + type >= EET_T_LAST) + { + CRIT("Preventing later bug due to unknow type: %i", type); + return ; + } + if (offset < 0) + { + CRIT("Preventing later buffer underrun : offset = %i", offset); + return ; + } + if (offset > edd->size) + { + CRIT("Preventing later buffer overrun : offset = %i in a structure of %i bytes", offset, edd->size); + return ; + } + if (group_type == EET_G_UNKNOWN && type != EET_T_UNKNOW) + { + if (offset + eet_basic_codec[type - 1].size > edd->size) + { + CRIT("Preventing later buffer overrun : offset = %i, size = %i in a structure of %i bytes", offset, eet_basic_codec[type - 1].size, edd->size); + return ; + } + } + else if ((offset + sizeof (void*)) > (unsigned int) edd->size) + { + CRIT("Preventing later buffer overrun : offset = %i, estimated size = %zu in a structure of %i bytes", offset, sizeof (void*), edd->size); + return ; + } - /* FIXME: Fail safely when realloc fail. */ + /* UNION, VARIANT type would not work with simple type, we need a way to map the type. */ + if ((group_type == EET_G_UNION + || group_type == EET_G_VARIANT) + && + (type != EET_T_UNKNOW + || !subtype + || !subtype->func.type_get + || !subtype->func.type_set)) + return; + + /* VARIANT type will only work if the map only contains EET_G_*, but not UNION, VARIANT and ARRAY. */ + if (group_type == EET_G_VARIANT) + { + int i; + + for (i = 0; i < subtype->elements.num; ++i) + if (subtype->elements.set[i].type != EET_T_UNKNOW + && subtype->elements.set[i].group_type > EET_G_VAR_ARRAY + && subtype->elements.set[i].group_type < EET_G_UNION) + return; + + subtype->unified_type = EINA_TRUE; + } + + if (subtype + && subtype->unified_type + && (type != EET_T_UNKNOW + || group_type < EET_G_UNION)) + return; + + /* Sanity check done, let allocate ! */ edd->elements.num++; - edd->elements.set = realloc(edd->elements.set, edd->elements.num * sizeof(Eet_Data_Element)); - if (!edd->elements.set) return; + tmp = realloc(edd->elements.set, edd->elements.num * sizeof(Eet_Data_Element)); + if (!tmp) + return; + + edd->elements.set = tmp; ede = &(edd->elements.set[edd->elements.num - 1]); ede->name = name; ede->directory_name_ptr = NULL; @@ -1120,27 +2022,36 @@ eet_data_descriptor_element_add(Eet_Data_Descriptor *edd, * Instead of handling it in encode/decode/dump/undump, we create an * implicit structure with only the simple type. */ - if (group_type > EET_G_UNKNOWN - && group_type < EET_G_LAST - && type != EET_T_UNKNOW - && subtype == NULL) + if ((group_type > EET_G_UNKNOWN) + && (group_type < EET_G_LAST) + && (((type > EET_T_UNKNOW) && (type < EET_T_STRING)) + || ((type > EET_T_NULL) && (type < EET_T_LAST))) + && (!subtype)) { - subtype = calloc(1, sizeof (Eet_Data_Descriptor)); - if (!subtype) return ; - subtype->name = "implicit"; - subtype->size = eet_basic_codec[type - 1].size; - memcpy(&subtype->func, &edd->func, sizeof(subtype->func)); - - eet_data_descriptor_element_add(subtype, eet_basic_codec[type - 1].name, type, - EET_G_UNKNOWN, 0, 0, /* 0, */NULL, NULL); - type = EET_T_UNKNOW; + subtype = calloc(1, sizeof (Eet_Data_Descriptor)); + if (!subtype) + return; + + subtype->name = "implicit"; + subtype->size = eet_basic_codec[type - 1].size; + memcpy(&subtype->func, &edd->func, sizeof(subtype->func)); + + eet_data_descriptor_element_add(subtype, + eet_basic_codec[type - 1].name, + type, + EET_G_UNKNOWN, + 0, + 0, + /* 0, */ NULL, + NULL); + type = EET_T_UNKNOW; } ede->type = type; ede->group_type = group_type; ede->offset = offset; ede->count = count; - /* FIXME: For the time being, EET_G_VAR_ARRAY will put the counter_offset in count. */ + /* FIXME: For the time being, VAR_ARRAY, UNION and VARIANT will put the counter_offset in count. */ ede->counter_offset = count; /* ede->counter_offset = counter_offset; */ ede->counter_name = counter_name; @@ -1149,61 +2060,173 @@ eet_data_descriptor_element_add(Eet_Data_Descriptor *edd, } EAPI void * -eet_data_read(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name) +eet_data_read_cipher(Eet_File *ef, + Eet_Data_Descriptor *edd, + const char *name, + const char *cipher_key) { const Eet_Dictionary *ed = NULL; - const void *data; - void *data_dec; - int size; - int required_free = 0; + const void *data = NULL; + void *data_dec; + Eet_Free_Context context; + int required_free = 0; + int size; ed = eet_dictionary_get(ef); - data = eet_read_direct(ef, name, &size); + if (!cipher_key) + data = eet_read_direct(ef, name, &size); + if (!data) { - required_free = 1; - data = eet_read(ef, name, &size); - if (!data) return NULL; + required_free = 1; + data = eet_read_cipher(ef, name, &size, cipher_key); + if (!data) + return NULL; } - data_dec = _eet_data_descriptor_decode(ed, edd, data, size, 0, NULL, NULL); + eet_free_context_init(&context); + data_dec = _eet_data_descriptor_decode(&context, ed, edd, data, size, NULL, 0); + eet_free_context_shutdown(&context); + if (required_free) - free((void*)data); + free((void *)data); return data_dec; } +EAPI Eet_Node * +eet_data_node_read_cipher(Eet_File *ef, + const char *name, + const char *cipher_key) +{ + const Eet_Dictionary *ed = NULL; + const void *data = NULL; + Eet_Node *result; + Eet_Free_Context context; + int required_free = 0; + int size; + + ed = eet_dictionary_get(ef); + + if (!cipher_key) + data = eet_read_direct(ef, name, &size); + + if (!data) + { + required_free = 1; + data = eet_read_cipher(ef, name, &size, cipher_key); + if (!data) + return NULL; + } + + eet_free_context_init(&context); + result = _eet_data_descriptor_decode(&context, ed, NULL, data, size, NULL, 0); + eet_free_context_shutdown(&context); + + if (required_free) + free((void *)data); + + return result; +} + +EAPI void * +eet_data_read(Eet_File *ef, + Eet_Data_Descriptor *edd, + const char *name) +{ + return eet_data_read_cipher(ef, edd, name, NULL); +} + EAPI int -eet_data_write(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name, const void *data, int compress) +eet_data_write_cipher(Eet_File *ef, + Eet_Data_Descriptor *edd, + const char *name, + const char *cipher_key, + const void *data, + int comp) { - Eet_Dictionary *ed; - void *data_enc; - int size; - int val; + Eet_Dictionary *ed; + void *data_enc; + int size; + int val; + + EINA_SAFETY_ON_NULL_RETURN_VAL(edd, 0); ed = eet_dictionary_get(ef); data_enc = _eet_data_descriptor_encode(ed, edd, data, &size); - if (!data_enc) return 0; - val = eet_write(ef, name, data_enc, size, compress); + if (!data_enc) + return 0; + + val = eet_write_cipher(ef, name, data_enc, size, comp, cipher_key); free(data_enc); return val; } -typedef struct _Eet_Free Eet_Free; -struct _Eet_Free +EAPI int +eet_data_write(Eet_File *ef, + Eet_Data_Descriptor *edd, + const char *name, + const void *data, + int comp) { - int ref; - int len[256]; - int num[256]; - void **list[256]; -}; + return eet_data_write_cipher(ef, edd, name, NULL, data, comp); +} + +static void +eet_free_context_init(Eet_Free_Context *context) +{ + unsigned int i = 0; + + memset(context, 0, sizeof (Eet_Free_Context)); + for (i = 0; i < EET_FREE_COUNT; ++i) + { + eina_array_step_set(&context->freelist.list[i], + sizeof (context->freelist.list[i]), + 32); + eina_array_step_set(&context->freelist_array.list[i], + sizeof (context->freelist.list[i]), + 32); + eina_array_step_set(&context->freelist_list.list[i], + sizeof (context->freelist.list[i]), + 32); + eina_array_step_set(&context->freelist_hash.list[i], + sizeof (context->freelist.list[i]), + 32); + eina_array_step_set(&context->freelist_str.list[i], + sizeof (context->freelist.list[i]), + 32); + eina_array_step_set(&context->freelist_direct_str.list[i], + sizeof (context->freelist.list[i]), + 32); + } +} + +static void +eet_free_context_shutdown(Eet_Free_Context *context) +{ + unsigned int i = 0; + + for (i = 0; i < EET_FREE_COUNT; ++i) + { + eina_array_flush(&context->freelist.list[i]); + eina_array_flush(&context->freelist_array.list[i]); + eina_array_flush(&context->freelist_list.list[i]); + eina_array_flush(&context->freelist_hash.list[i]); + eina_array_flush(&context->freelist_str.list[i]); + eina_array_flush(&context->freelist_direct_str.list[i]); + } +} static int _eet_free_hash(void *data) { +#ifdef _WIN64 + __int64 ptr = (UINT_PTR)data; +#else /* ifdef _WIN64 */ unsigned long ptr = (unsigned long)(data); +#endif /* ifdef _WIN64 */ int hash; hash = ptr; @@ -1211,173 +2234,296 @@ _eet_free_hash(void *data) hash ^= ptr >> 16; hash ^= ptr >> 24; -#if LONG_BIT != 32 +#if defined (_WIN64) || ((!defined (_WIN32)) && (LONG_BIT != 32)) hash ^= ptr >> 32; hash ^= ptr >> 40; hash ^= ptr >> 48; hash ^= ptr >> 56; -#endif +#endif /* if defined (_WIN64) || ((!defined (_WIN32)) && (LONG_BIT != 32)) */ return hash & 0xFF; } static void -_eet_free_add(Eet_Free *ef, void *data) +_eet_free_add(Eet_Free *ef, + void *data) { + void *track; + Eina_Array_Iterator it; + unsigned int i; int hash; - int i; hash = _eet_free_hash(data); - for (i = 0; i < ef->num[hash]; ++i) - if (ef->list[hash][i] == data) return; + EINA_ARRAY_ITER_NEXT(&ef->list[hash], i, track, it) + if (track == data) + return; - ef->num[hash]++; - if (ef->num[hash] > ef->len[hash]) - { - void **tmp; + eina_array_push(&ef->list[hash], data); +} + +#if 0 +static void +_eet_free_del(Eet_Free *ef, + void *data) +{ + void *track; + Eina_Array_Iterator it; + unsigned int i; + int hash; - tmp = realloc(ef->list[hash], (ef->len[hash] + 16) * sizeof(void*)); - if (!tmp) return ; + hash = _eet_free_hash(data); - ef->len[hash] += 16; - ef->list[hash] = tmp; + EINA_ARRAY_ITER_NEXT(&ef->list[hash], i, track, it) + if (track == data) + { + eina_array_data_set(&ef->list[hash], i, NULL); + return; } - ef->list[hash][ef->num[hash] - 1] = data; } + +#endif + static void _eet_free_reset(Eet_Free *ef) { - int i; + unsigned int i; - if (ef->ref > 0) return ; - for (i = 0; i < 256; ++i) - { - ef->len[i] = 0; - ef->num[i] = 0; - if (ef->list[i]) free(ef->list[i]); - ef->list[i] = NULL; - } + if (ef->ref > 0) + return; + + for (i = 0; i < EET_FREE_COUNT; ++i) + eina_array_clean(&ef->list[i]); } + static void _eet_free_ref(Eet_Free *ef) { ef->ref++; } + static void _eet_free_unref(Eet_Free *ef) { ef->ref--; } -static Eet_Free freelist = { 0, { 0 }, { 0 }, { NULL } }; - -#define _eet_freelist_add(Data) _eet_free_add(&freelist, Data); -#define _eet_freelist_reset() _eet_free_reset(&freelist); -#define _eet_freelist_ref() _eet_free_ref(&freelist); -#define _eet_freelist_unref() _eet_free_unref(&freelist); +#define _eet_freelist_add(Ctx, Data) _eet_free_add(&Ctx->freelist, Data); +#define _eet_freelist_del(Ctx, Data) _eet_free_del(&Ctx->freelist, Data); +#define _eet_freelist_reset(Ctx) _eet_free_reset(&Ctx->freelist); +#define _eet_freelist_ref(Ctx) _eet_free_ref(&Ctx->freelist); +#define _eet_freelist_unref(Ctx) _eet_free_unref(&Ctx->freelist); static void -_eet_freelist_free(Eet_Data_Descriptor *edd) +_eet_freelist_free(Eet_Free_Context *context, + Eet_Data_Descriptor *edd) { - int j; - int i; + void *track; + Eina_Array_Iterator it; + unsigned int j; + unsigned int i; - if (freelist.ref > 0) return; - for (j = 0; j < 256; ++j) - for (i = 0; i < freelist.num[j]; ++i) + if (context->freelist.ref > 0) + return; + + for (j = 0; j < EET_FREE_COUNT; ++j) + EINA_ARRAY_ITER_NEXT(&context->freelist.list[j], i, track, it) + if (track) { - if (edd) - edd->func.mem_free(freelist.list[j][i]); - else - free(freelist.list[j][i]); + if (edd) + edd->func.mem_free(track); + else + free(track); } - _eet_free_reset(&freelist); + _eet_free_reset(&context->freelist); } -static Eet_Free freelist_list = { 0, { 0 }, { 0 }, { NULL } }; - -#define _eet_freelist_list_add(Data) _eet_free_add(&freelist_list, Data); -#define _eet_freelist_list_reset() _eet_free_reset(&freelist_list); -#define _eet_freelist_list_ref() _eet_free_ref(&freelist_list); -#define _eet_freelist_list_unref() _eet_free_unref(&freelist_list); +#define _eet_freelist_array_add(Ctx, Data) _eet_free_add(&Ctx->freelist_array, Data); +#define _eet_freelist_array_del(Ctx, Data) _eet_free_del(&Ctx->freelist_array, Data); +#define _eet_freelist_array_reset(Ctx) _eet_free_reset(&Ctx->freelist_array); +#define _eet_freelist_array_ref(Ctx) _eet_free_ref(&Ctx->freelist_array); +#define _eet_freelist_array_unref(Ctx) _eet_free_unref(&Ctx->freelist_array); static void -_eet_freelist_list_free(Eet_Data_Descriptor *edd) +_eet_freelist_array_free(Eet_Free_Context *context, + Eet_Data_Descriptor *edd) { - int j; - int i; + void *track; + Eina_Array_Iterator it; + unsigned int j; + unsigned int i; - if (freelist_list.ref > 0) return; - for (j = 0; j < 256; ++j) - for (i = 0; i < freelist_list.num[j]; ++i) + if (context->freelist_array.ref > 0) + return; + + for (j = 0; j < EET_FREE_COUNT; ++j) + EINA_ARRAY_ITER_NEXT(&context->freelist_array.list[j], i, track, it) + if (track) { - if (edd) - edd->func.list_free(*((void**)(freelist_list.list[j][i]))); + if (edd) + { + if (edd->func.array_free) + edd->func.array_free(track); + else + edd->func.mem_free(track); + } + else + free(track); } - _eet_free_reset(&freelist_list); + _eet_free_reset(&context->freelist_array); } -static Eet_Free freelist_str = { 0, { 0 }, { 0 }, { NULL } }; +#define _eet_freelist_list_add(Ctx, Data) _eet_free_add(&Ctx->freelist_list, Data); +#define _eet_freelist_list_del(Ctx, Data) _eet_free_del(&Ctx->freelist_list, Data); +#define _eet_freelist_list_reset(Ctx) _eet_free_reset(&Ctx->freelist_list); +#define _eet_freelist_list_ref(Ctx) _eet_free_ref(&Ctx->freelist_list); +#define _eet_freelist_list_unref(Ctx) _eet_free_unref(&Ctx->freelist_list); + +static void +_eet_freelist_list_free(Eet_Free_Context *context, + Eet_Data_Descriptor *edd) +{ + void *track; + Eina_Array_Iterator it; + unsigned int j; + unsigned int i; + + if (context->freelist_list.ref > 0) + return; + + for (j = 0; j < EET_FREE_COUNT; ++j) + EINA_ARRAY_ITER_NEXT(&context->freelist_list.list[j], i, track, it) + if (track) + { + if (edd) + edd->func.list_free(*((void **)(track))); + } + _eet_free_reset(&context->freelist_list); +} -#define _eet_freelist_str_add(Data) _eet_free_add(&freelist_str, Data); -#define _eet_freelist_str_reset() _eet_free_reset(&freelist_str); -#define _eet_freelist_str_ref() _eet_free_ref(&freelist_str); -#define _eet_freelist_str_unref() _eet_free_unref(&freelist_str); +#define _eet_freelist_str_add(Ctx, Data) _eet_free_add(&Ctx->freelist_str, Data); +#define _eet_freelist_str_del(Ctx, Data) _eet_free_del(&Ctx->freelist_str, Data); +#define _eet_freelist_str_reset(Ctx) _eet_free_reset(&Ctx->freelist_str); +#define _eet_freelist_str_ref(Ctx) _eet_free_ref(&Ctx->freelist_str); +#define _eet_freelist_str_unref(Ctx) _eet_free_unref(&Ctx->freelist_str); static void -_eet_freelist_str_free(Eet_Data_Descriptor *edd) +_eet_freelist_str_free(Eet_Free_Context *context, + Eet_Data_Descriptor *edd) { - int j; - int i; + void *track; + Eina_Array_Iterator it; + unsigned int j; + unsigned int i; + + if (context->freelist_str.ref > 0) + return; - if (freelist_str.ref > 0) return; - for (j = 0; j < 256; ++j) - for (i = 0; i < freelist_str.num[j]; ++i) + for (j = 0; j < EET_FREE_COUNT; ++j) + EINA_ARRAY_ITER_NEXT(&context->freelist_str.list[j], i, track, it) + if (track) { - if (edd) - edd->func.str_free(freelist_str.list[j][i]); - else - free(freelist_str.list[j][i]); + if (edd) + edd->func.str_free(track); + else + free(track); } - _eet_free_reset(&freelist_str); + _eet_free_reset(&context->freelist_str); } -static Eet_Free freelist_direct_str = { 0, { 0 }, { 0 }, { NULL } }; +#define _eet_freelist_direct_str_add(Ctx, Data) _eet_free_add(&Ctx->freelist_direct_str, Data); +#define _eet_freelist_direct_str_del(Ctx, Data) _eet_free_del(&Ctx->freelist_direct_str, Data); +#define _eet_freelist_direct_str_reset(Ctx) _eet_free_reset(&Ctx->freelist_direct_str); +#define _eet_freelist_direct_str_ref(Ctx) _eet_free_ref(&Ctx->freelist_direct_str); +#define _eet_freelist_direct_str_unref(Ctx) _eet_free_unref(&Ctx->freelist_direct_str); + +static void +_eet_freelist_direct_str_free(Eet_Free_Context *context, + Eet_Data_Descriptor *edd) +{ + void *track; + Eina_Array_Iterator it; + unsigned int j; + unsigned int i; + + if (context->freelist_direct_str.ref > 0) + return; -#define _eet_freelist_direct_str_add(Data) _eet_free_add(&freelist_direct_str, Data); -#define _eet_freelist_direct_str_reset() _eet_free_reset(&freelist_direct_str); -#define _eet_freelist_direct_str_ref() _eet_free_ref(&freelist_direct_str); -#define _eet_freelist_direct_str_unref() _eet_free_unref(&freelist_direct_str); + for (j = 0; j < EET_FREE_COUNT; ++j) + EINA_ARRAY_ITER_NEXT(&context->freelist_str.list[j], i, track, it) + if (track) + { + if (edd) + edd->func.str_direct_free(track); + else + free(track); + } + _eet_free_reset(&context->freelist_direct_str); +} + +#define _eet_freelist_hash_add(Ctx, Data) _eet_free_add(&Ctx->freelist_hash, Data); +#define _eet_freelist_hash_del(Ctx, Data) _eet_free_del(&Ctx->freelist_hash, Data); +#define _eet_freelist_hash_reset(Ctx) _eet_free_reset(&Ctx->freelist_hash); +#define _eet_freelist_hash_ref(Ctx) _eet_free_ref(&Ctx->freelist_hash); +#define _eet_freelist_hash_unref(Ctx) _eet_free_unref(&Ctx->freelist_hash); static void -_eet_freelist_direct_str_free(Eet_Data_Descriptor *edd) +_eet_freelist_hash_free(Eet_Free_Context *context, + Eet_Data_Descriptor *edd) { - int j; - int i; + void *track; + Eina_Array_Iterator it; + unsigned int j; + unsigned int i; - if (freelist_str.ref > 0) return; - for (j = 0; j < 256; ++j) - for (i = 0; i < freelist_str.num[j]; ++i) + if (context->freelist_hash.ref > 0) + return; + + for (j = 0; j < EET_FREE_COUNT; ++j) + EINA_ARRAY_ITER_NEXT(&context->freelist_hash.list[j], i, track, it) + if (track) { - if (edd) - edd->func.str_direct_free(freelist_str.list[j][i]); - else - free(freelist_str.list[j][i]); + if (edd) + edd->func.hash_free(track); + else + free(track); } - _eet_free_reset(&freelist_str); + _eet_free_reset(&context->freelist_hash); +} + +static void +_eet_freelist_all_ref(Eet_Free_Context *freelist_context) +{ + _eet_freelist_ref(freelist_context); + _eet_freelist_str_ref(freelist_context); + _eet_freelist_list_ref(freelist_context); + _eet_freelist_hash_ref(freelist_context); + _eet_freelist_direct_str_ref(freelist_context); +} + +static void +_eet_freelist_all_unref(Eet_Free_Context *freelist_context) +{ + _eet_freelist_unref(freelist_context); + _eet_freelist_str_unref(freelist_context); + _eet_freelist_list_unref(freelist_context); + _eet_freelist_hash_unref(freelist_context); + _eet_freelist_direct_str_unref(freelist_context); } static int -eet_data_descriptor_encode_hash_cb(void *hash __UNUSED__, const char *key, void *hdata, void *fdata) +eet_data_descriptor_encode_hash_cb(void *hash __UNUSED__, + const char *cipher_key, + void *hdata, + void *fdata) { - Eet_Dictionary *ed; - Eet_Data_Encode_Hash_Info *edehi; - Eet_Data_Stream *ds; - Eet_Data_Element *ede; - Eet_Data_Chunk *echnk; - void *data = NULL; - int size; + Eet_Dictionary *ed; + Eet_Data_Encode_Hash_Info *edehi; + Eet_Data_Stream *ds; + Eet_Data_Element *ede; + Eet_Data_Chunk *echnk; + void *data = NULL; + int size; edehi = fdata; ede = edehi->ede; @@ -1387,84 +2533,54 @@ eet_data_descriptor_encode_hash_cb(void *hash __UNUSED__, const char *key, void /* Store key */ data = eet_data_put_type(ed, EET_T_STRING, - &key, - &size); + &cipher_key, + &size); if (data) { - echnk = eet_data_chunk_new(data, size, ede->name, ede->type, ede->group_type); - eet_data_chunk_put(ed, echnk, ds); - eet_data_chunk_free(echnk); - free(data); - data = NULL; + echnk = eet_data_chunk_new(data, + size, + ede->name, + ede->type, + ede->group_type); + eet_data_chunk_put(ed, echnk, ds); + eet_data_chunk_free(echnk); + free(data); + data = NULL; } - EET_ASSERT(!IS_SIMPLE_TYPE(ede->type), return 1); + EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)), return ); /* Store data */ - if (ede->subtype) - data = _eet_data_descriptor_encode(ed, - ede->subtype, - hdata, - &size); - if (data) - { - echnk = eet_data_chunk_new(data, size, ede->name, ede->type, ede->group_type); - eet_data_chunk_put(ed, echnk, ds); - eet_data_chunk_free(echnk); - free(data); - data = NULL; - } - return 1; -} - -static char * -_eet_data_string_escape(const char *str) -{ - char *s, *sp; - const char *strp; - int sz = 0; - - for (strp = str; *strp; strp++) - { - if (*strp == '\"') sz += 2; - else if (*strp == '\\') sz += 2; - else sz += 1; - } - s = malloc(sz + 1); - if (!s) return NULL; - for (strp = str, sp = s; *strp; strp++, sp++) + if (ede->type >= EET_T_STRING) + eet_data_put_unknown(ed, NULL, ede, ds, &hdata); + else { - if (*strp == '\"') - { - *sp = '\\'; - sp++; - } - else if (*strp == '\\') - { - *sp = '\\'; - sp++; - } - *sp = *strp; + if (ede->subtype) + data = _eet_data_descriptor_encode(ed, + ede->subtype, + hdata, + &size); + + if (data) + { + echnk = eet_data_chunk_new(data, + size, + ede->name, + ede->type, + ede->group_type); + eet_data_chunk_put(ed, echnk, ds); + eet_data_chunk_free(echnk); + free(data); + data = NULL; + } } - *sp = 0; - return s; -} - -static void -_eet_data_dump_string_escape(void *dumpdata, void dumpfunc(void *data, const char *str), const char *str) -{ - char *s; - s = _eet_data_string_escape(str); - if (s) - { - dumpfunc(dumpdata, s); - free(s); - } + return 1; } static char * -_eet_data_dump_token_get(const char *src, int *len) +_eet_data_dump_token_get(const char *src, + int *len) { const char *p; char *tok = NULL; @@ -1472,374 +2588,408 @@ _eet_data_dump_token_get(const char *src, int *len) int in_quote = 0; int tlen = 0, tsize = 0; -#define TOK_ADD(x) \ - { \ - tlen++; \ - if (tlen >= tsize) \ - { \ - tsize += 32; \ - tok = realloc(tok, tsize); \ - } \ - tok[tlen - 1] = x; \ - } +#define TOK_ADD(x) \ + do { \ + tlen++; \ + if (tlen >= tsize) \ + { \ + tsize += 32; \ + tok = realloc(tok, tsize); \ + } \ + tok[tlen - 1] = x; \ + } while (0) for (p = src; *len > 0; p++, (*len)--) { - if (in_token) - { - if (in_quote) - { - if ((p[0] == '\"') && (p > src) && (p[-1] != '\\')) - { - in_quote = 0; - } - else if ((p[0] == '\\') && (*len > 1) && (p[1] == '\"')) - { - /* skip */ - } - else if ((p[0] == '\\') && (p > src) && (p[-1] == '\\')) - { - /* skip */ - } - else - TOK_ADD(p[0]); - } - else - { - if (p[0] == '\"') in_quote = 1; - else - { - if ((isspace(p[0])) || (p[0] == ';')) /* token ends here */ - { - TOK_ADD(0); - (*len)--; - return tok; - } - else - TOK_ADD(p[0]); - } - } - } - else - { - if (!((isspace(p[0])) || (p[0] == ';'))) - { - in_token = 1; - (*len)++; - p--; - } - } + if (in_token) + { + if (in_quote) + { + if ((p[0] == '\"') && (p > src) && (p[-1] != '\\')) + in_quote = 0; + else if ((p[0] == '\\') && (*len > 1) && + (p[1] == '\"')) + { +/* skip */ + } + else if ((p[0] == '\\') && (p > src) && (p[-1] == '\\')) + { +/* skip */ + } + else if ((p[0] == '\\') && (*len > 1) && (p[1] == 'n')) + { +/* skip */ + } + else if ((p[0] == 'n') && (p > src) && (p[-1] == '\\')) + TOK_ADD('\n'); + else + TOK_ADD(p[0]); + } + else + { + if (p[0] == '\"') + in_quote = 1; + else + { + if ((isspace(p[0])) || (p[0] == ';')) /* token ends here */ + { + TOK_ADD(0); + (*len)--; + return tok; + } + else + TOK_ADD(p[0]); + } + } + } + else if (!((isspace(p[0])) || (p[0] == ';'))) + { + in_token = 1; + (*len)++; + p--; + } } if (in_token) { - TOK_ADD(0); - return tok; + TOK_ADD(0); + return tok; } - if (tok) free(tok); + + if (tok) + free(tok); + return NULL; } -typedef struct _Node Node; - -struct _Node -{ - int type; - int count; - char *name; - char *key; - Node *values; - Node *prev; - Node *next; - Node *parent; - union { - char c; - short s; - int i; - long long l; - float f; - double d; - unsigned char uc; - unsigned short us; - unsigned int ui; - unsigned long long ul; - char *str; - } data; -}; - static void -_eet_data_dump_free(Node *node) +eet_data_encode(Eet_Dictionary *ed, + Eet_Data_Stream *ds, + void *data, + const char *name, + int size, + int type, + int group_type) { - Node *n, *n2; + Eet_Data_Chunk *echnk; - switch (node->type) - { - case EET_G_UNKNOWN: - case EET_G_ARRAY: - case EET_G_VAR_ARRAY: - case EET_G_LIST: - case EET_G_HASH: - if (node->key) free(node->key); - for (n = node->values; n;) - { - n2 = n; - n = n->next; - _eet_data_dump_free(n2); - } - break; - case EET_T_CHAR: - case EET_T_SHORT: - case EET_T_INT: - case EET_T_LONG_LONG: - case EET_T_FLOAT: - case EET_T_DOUBLE: - case EET_T_UCHAR: - case EET_T_USHORT: - case EET_T_UINT: - case EET_T_ULONG_LONG: - break; - case EET_T_INLINED_STRING: - case EET_T_STRING: - if (node->data.str) free(node->data.str); - break; - default: - break; - } - free(node); + if (!data) + type = EET_T_NULL; + + if (group_type != EET_G_UNKNOWN) + if (type >= EET_T_LAST) + type = EET_T_UNKNOW; + + echnk = eet_data_chunk_new(data, size, name, type, group_type); + eet_data_chunk_put(ed, echnk, ds); + eet_data_chunk_free(echnk); + free(data); } static void * -_eet_data_dump_encode(Eet_Dictionary *ed, - Node *node, - int *size_ret) +_eet_data_dump_encode(int parent_type, + Eet_Dictionary *ed, + Eet_Node *node, + int *size_ret) { - Eet_Data_Chunk *chnk = NULL, *echnk = NULL; + Eet_Data_Chunk *chnk = NULL; Eet_Data_Stream *ds; void *cdata, *data; int csize, size; - Node *n; + int count; + int child_type; + Eet_Node *n; - if (words_bigendian == -1) + if (_eet_data_words_bigendian == -1) { - unsigned long int v; + unsigned long int v; - v = htonl(0x12345678); - if (v == 0x12345678) words_bigendian = 1; - else words_bigendian = 0; + v = htonl(0x12345678); + if (v == 0x12345678) + _eet_data_words_bigendian = 1; + else + _eet_data_words_bigendian = 0; } + if (!node) + return NULL; + ds = eet_data_stream_new(); - if (!ds) return NULL; + if (!ds) + return NULL; switch (node->type) { case EET_G_UNKNOWN: - for (n = node->values; n; n = n->next) - { - data = _eet_data_dump_encode(ed, n, &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - } - break; + for (n = node->values; n; n = n->next) + { + data = _eet_data_dump_encode(node->type, ed, n, &size); + if (data) + { + eet_data_stream_write(ds, data, size); + free(data); + } + } + break; + case EET_G_ARRAY: case EET_G_VAR_ARRAY: - data = eet_data_put_type(ed, - EET_T_INT, - &node->count, - &size); - if (data) - { - echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type); - eet_data_chunk_put(ed, echnk, ds); - eet_data_chunk_free(echnk); - free(data); - } - for (n = node->values; n; n = n->next) - { - data = _eet_data_dump_encode(ed, n, &size); - if (data) - { - echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type); - eet_data_chunk_put(ed, echnk, ds); - eet_data_chunk_free(echnk); - free(data); - } - } - - /* Array is somekind of special case, so we should embed it inside another chunk. */ - *size_ret = ds->pos; - cdata = ds->data; - - ds->data = NULL; - ds->size = 0; - eet_data_stream_free(ds); - - return cdata; + for (child_type = EET_T_NULL, n = node->values; n; n = n->next) + { + if (n->type != EET_T_NULL) + { + child_type = n->type; + break; + } + } + + data = eet_data_put_type(ed, + EET_T_INT, + &node->count, + &size); + eet_data_encode(ed, + ds, + data, + node->name, + size, + child_type, + node->type); + + count = node->count; + + for (n = node->values; n; n = n->next) + { + int pos = ds->pos; + + switch (n->type) + { + case EET_T_STRING: + case EET_T_INLINED_STRING: + data = eet_data_put_type(ed, + n->type, + &(n->data.value.str), + &size); + if (data) + eet_data_encode(ed, + ds, + data, + node->name, + size, + n->type, + node->type); + + break; + + case EET_T_NULL: + continue; + + default: + data = _eet_data_dump_encode(n->type, ed, n, &size); + eet_data_encode(ed, + ds, + data, + node->name, + size, + n->type, + node->type); + break; + } /* switch */ + if (ds->pos != pos) + count--; + } + + for (; count; count--) + { + eet_data_encode(ed, + ds, + NULL, + node->name, + 0, + EET_T_NULL, + node->type); + } + + /* Array is somekind of special case, so we should embed it inside another chunk. */ + *size_ret = ds->pos; + cdata = ds->data; + + ds->data = NULL; + ds->size = 0; + eet_data_stream_free(ds); + + return cdata; + break; + case EET_G_LIST: - for (n = node->values; n; n = n->next) - { - data = _eet_data_dump_encode(ed, n, &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - } - break; + for (n = node->values; n; n = n->next) + { + switch (n->type) + { + case EET_T_STRING: + case EET_T_INLINED_STRING: + data = eet_data_put_type(ed, + n->type, + &(n->data.value.str), + &size); + if (data) + eet_data_encode(ed, + ds, + data, + node->name, + size, + n->type, + node->type); + + break; + + case EET_T_NULL: + continue; + + default: + data = _eet_data_dump_encode(node->type, ed, n, &size); + eet_data_encode(ed, + ds, + data, + node->name, + size, + n->type, + node->type); + } /* switch */ + } + + /* List is another somekind of special case, every chunk is embed inside a list chunk. */ + *size_ret = ds->pos; + cdata = ds->data; + + ds->data = NULL; + ds->size = 0; + eet_data_stream_free(ds); + + return cdata; + break; + case EET_G_HASH: - if (node->key) - { - data = eet_data_put_type(ed, + if (node->key) + { + data = eet_data_put_type(ed, EET_T_STRING, - &node->key, - &size); - if (data) - { - echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type); - eet_data_chunk_put(ed, echnk, ds); - eet_data_chunk_free(echnk); - free(data); - } - } - for (n = node->values; n; n = n->next) - { - data = _eet_data_dump_encode(ed, n, &size); - if (data) - { - echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type); - eet_data_chunk_put(ed, echnk, ds); - eet_data_chunk_free(echnk); - free(data); - } - } - - /* Hash is somekind of special case, so we should embed it inside another chunk. */ - *size_ret = ds->pos; - cdata = ds->data; - - ds->data = NULL; - ds->size = 0; - eet_data_stream_free(ds); - - return cdata; - case EET_T_CHAR: - data = eet_data_put_type(ed, node->type, &(node->data.c), &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - break; - case EET_T_SHORT: - data = eet_data_put_type(ed, node->type, &(node->data.s), &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - break; - case EET_T_INT: - data = eet_data_put_type(ed, node->type, &(node->data.i), &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - break; - case EET_T_LONG_LONG: - data = eet_data_put_type(ed, node->type, &(node->data.l), &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - break; - case EET_T_FLOAT: - data = eet_data_put_type(ed, node->type, &(node->data.f), &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - break; - case EET_T_DOUBLE: - data = eet_data_put_type(ed, node->type, &(node->data.d), &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - break; - case EET_T_UCHAR: - data = eet_data_put_type(ed, node->type, &(node->data.uc), &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - break; - case EET_T_USHORT: - data = eet_data_put_type(ed, node->type, &(node->data.us), &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - break; - case EET_T_UINT: - data = eet_data_put_type(ed, node->type, &(node->data.ui), &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - break; - case EET_T_ULONG_LONG: - data = eet_data_put_type(ed, node->type, &(node->data.ul), &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - break; - case EET_T_INLINED_STRING: - data = eet_data_put_type(ed, node->type, &(node->data.str), &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - break; - case EET_T_STRING: - data = eet_data_put_type(ed, node->type, &(node->data.str), &size); - if (data) - { - eet_data_stream_write(ds, data, size); - free(data); - } - break; + &node->key, + &size); + eet_data_encode(ed, + ds, + data, + node->name, + size, + node->type, + node->type); + } + else + /* A Hash without key will not decode correctly. */ + return NULL; + + for (n = node->values; n; n = n->next) + { + switch (n->type) + { + case EET_T_STRING: + case EET_T_INLINED_STRING: + data = eet_data_put_type(ed, + n->type, + &(n->data.value.str), + &size); + if (data) + eet_data_encode(ed, + ds, + data, + node->name, + size, + n->type, + node->type); + + break; + + case EET_T_NULL: + continue; + + default: + data = _eet_data_dump_encode(node->type, ed, n, &size); + eet_data_encode(ed, + ds, + data, + node->name, + size, + n->type, + node->type); + } /* switch */ + } + + /* Hash is somekind of special case, so we should embed it inside another chunk. */ + *size_ret = ds->pos; + cdata = ds->data; + + eet_data_stream_flush(ds); + + return cdata; + + case EET_T_NULL: + break; + +#define EET_DATA_NODE_ENCODE(Eet_Type, Type) \ +case Eet_Type: \ + data = eet_data_put_type(ed, node->type, &(node->data.value.Type), &size); \ + if (data) \ + { \ + eet_data_encode(ed, \ + ds, \ + data, \ + node->name, \ + size, \ + node->type, \ + parent_type); \ + cdata = ds->data; \ + *size_ret = ds->pos; \ + eet_data_stream_flush(ds); \ + return cdata; \ + } /* switch */ \ + break; + + EET_DATA_NODE_ENCODE(EET_T_CHAR, c); + EET_DATA_NODE_ENCODE(EET_T_SHORT, s); + EET_DATA_NODE_ENCODE(EET_T_INT, i); + EET_DATA_NODE_ENCODE(EET_T_LONG_LONG, l); + EET_DATA_NODE_ENCODE(EET_T_FLOAT, f); + EET_DATA_NODE_ENCODE(EET_T_DOUBLE, d); + EET_DATA_NODE_ENCODE(EET_T_UCHAR, uc); + EET_DATA_NODE_ENCODE(EET_T_USHORT, us); + EET_DATA_NODE_ENCODE(EET_T_UINT, ui); + EET_DATA_NODE_ENCODE(EET_T_ULONG_LONG, ul); + EET_DATA_NODE_ENCODE(EET_T_INLINED_STRING, str); + EET_DATA_NODE_ENCODE(EET_T_STRING, str); + default: - break; + break; } if ((node->type >= EET_G_UNKNOWN) && (node->type < EET_G_LAST)) - chnk = eet_data_chunk_new(ds->data, ds->pos, node->name, EET_T_UNKNOW, node->type); + chnk = eet_data_chunk_new(ds->data, + ds->pos, + node->name, + EET_T_UNKNOW, + node->type); else - chnk = eet_data_chunk_new(ds->data, ds->pos, node->name, node->type, EET_G_UNKNOWN); - ds->data = NULL; - ds->size = 0; - eet_data_stream_free(ds); + chnk = eet_data_chunk_new(ds->data, + ds->pos, + node->name, + node->type, + EET_G_UNKNOWN); + + eet_data_stream_flush(ds); ds = eet_data_stream_new(); eet_data_chunk_put(ed, chnk, ds); cdata = ds->data; csize = ds->pos; - ds->data = NULL; - ds->size = 0; - eet_data_stream_free(ds); + eet_data_stream_flush(ds); *size_ret = csize; free(chnk->data); @@ -1850,729 +3000,583 @@ _eet_data_dump_encode(Eet_Dictionary *ed, static void * _eet_data_dump_parse(Eet_Dictionary *ed, - int *size_ret, - const char *src, - int size) + int *size_ret, + const char *src, + int size) { void *cdata = NULL; - const char *p; -#define M_NONE 0 + const char *p = NULL; +#define M_NONE 0 #define M_STRUCT 1 -#define M_ 2 +#define M_ 2 int left, jump; - Node *node_base = NULL; - Node *node = NULL; - Node *n, *nn; + Eet_Node *node_base = NULL; + Eet_Node *node = NULL; + Eet_Node *n = NULL, *nn = NULL; /* FIXME; handle parse errors */ #define TOK_GET(t) \ - jump = left; t = _eet_data_dump_token_get(p, &left); p += jump - left; + jump = left; t = _eet_data_dump_token_get(p, &left); p += jump - left; left = size; - for (p = src; p < (src + size);) - { - char *tok1, *tok2, *tok3, *tok4; - - TOK_GET(tok1); - if (tok1) - { - if (!strcmp(tok1, "group")) - { - TOK_GET(tok2); - if (tok2) - { - TOK_GET(tok3); - if (tok3) - { - TOK_GET(tok4); - if (tok4) - { - if (!strcmp(tok4, "{")) - { - /* we have 'group NAM TYP {' */ - n = calloc(1, sizeof(Node)); - if (n) - { - n->parent = node; - if (!node_base) - { - node_base = n; - } - if (!node) - { - node = n; - } - else - { - /* append node */ - if (!node->values) - node->values = n; - else - { - for (nn = node->values; nn; nn = nn->next) - { - if (!nn->next) - { - nn->next = n; - n->prev = nn; - break; - } - } - } - } - n->name = strdup(tok2); - if (!strcmp(tok3, "struct")) n->type = EET_G_UNKNOWN; - else if (!strcmp(tok3, "array")) n->type = EET_G_ARRAY; - else if (!strcmp(tok3, "var_array")) n->type = EET_G_VAR_ARRAY; - else if (!strcmp(tok3, "list")) n->type = EET_G_LIST; - else if (!strcmp(tok3, "hash")) n->type = EET_G_HASH; - else - { - printf("ERROR: group type '%s' invalid.\n", tok3); - } - node = n; - } - } - free(tok4); - } - free(tok3); - } - free(tok2); - } - } - else if (!strcmp(tok1, "value")) - { - TOK_GET(tok2); - if (tok2) - { - TOK_GET(tok3); - if (tok3) - { - TOK_GET(tok4); - if (tok4) - { - /* we have 'value NAME TYP XXX' */ - if (node_base) - { - n = calloc(1, sizeof(Node)); - if (n) - { - n->parent = node; - /* append node */ - if (!node->values) - node->values = n; - else - { - for (nn = node->values; nn; nn = nn->next) - { - if (!nn->next) - { - nn->next = n; - n->prev = nn; - break; - } - } - } - n->name = strdup(tok2); - if (!strcmp(tok3, "char:")) - { - n->type = EET_T_CHAR; - sscanf(tok4, "%hhi", &(n->data.c)); - } - else if (!strcmp(tok3, "short:")) - { - n->type = EET_T_SHORT; - sscanf(tok4, "%hi", &(n->data.s)); - } - else if (!strcmp(tok3, "int:")) - { - n->type = EET_T_INT; - sscanf(tok4, "%i", &(n->data.i)); - } - else if (!strcmp(tok3, "long_long:")) - { - n->type = EET_T_LONG_LONG; - sscanf(tok4, "%lli", &(n->data.l)); - } - else if (!strcmp(tok3, "float:")) - { - n->type = EET_T_FLOAT; - sscanf(tok4, "%f", &(n->data.f)); - } - else if (!strcmp(tok3, "double:")) - { - n->type = EET_T_DOUBLE; - sscanf(tok4, "%lf", &(n->data.d)); - } - else if (!strcmp(tok3, "uchar:")) - { - n->type = EET_T_UCHAR; - sscanf(tok4, "%hhu", &(n->data.uc)); - } - else if (!strcmp(tok3, "ushort:")) - { - n->type = EET_T_USHORT; - sscanf(tok4, "%hu", &(n->data.us)); - } - else if (!strcmp(tok3, "uint:")) - { - n->type = EET_T_UINT; - sscanf(tok4, "%u", &(n->data.ui)); - } - else if (!strcmp(tok3, "ulong_long:")) - { - n->type = EET_T_ULONG_LONG; - sscanf(tok4, "%llu", &(n->data.ul)); - } - else if (!strcmp(tok3, "string:")) - { - n->type = EET_T_STRING; - n->data.str = strdup(tok4); - } - else if (!strcmp(tok3, "inlined:")) - { - n->type = EET_T_INLINED_STRING; - n->data.str = strdup(tok4); - } - else - { - printf("ERROR: value type '%s' invalid.\n", tok4); - } - } - } - free(tok4); - } - free(tok3); - } - free(tok2); - } - } - else if (!strcmp(tok1, "key")) - { - TOK_GET(tok2); - if (tok2) - { - /* we have 'key NAME' */ - if (node) - { - node->key = strdup(tok2); - } - free(tok2); - } - } - else if (!strcmp(tok1, "count")) - { - TOK_GET(tok2); - if (tok2) - { - /* we have a 'count COUNT' */ - if (node) - { - sscanf(tok2, "%i", &(node->count)); - } - free(tok2); - } - } - else if (!strcmp(tok1, "}")) - { - /* we have an end of the group */ - if (node) node = node->parent; - } - free(tok1); - } + for (p = src; p < (src + size); ) + { + char *tok1, *tok2, *tok3, *tok4; + + TOK_GET(tok1); + if (tok1) + { + if (!strcmp(tok1, "group")) + { + TOK_GET(tok2); + if (tok2) + { + TOK_GET(tok3); + if (tok3) + { + TOK_GET(tok4); + if (tok4) + { + if (!strcmp(tok4, "{")) + { +/* we have 'group NAM TYP {' */ + n = eet_node_new(); + if (n) + { + n->parent = node; + if (!node_base) + node_base = n; + + if (node) + { +/* append node */ + if (!node->values) + node->values = n; + else + for (nn = node->values; nn; + nn = nn->next) + { + if (!nn->next) + { + nn->next = n; + break; + } + } + } + + n->name = eina_stringshare_add(tok2); + if (!strcmp(tok3, "struct")) + n->type = EET_G_UNKNOWN; + else if (!strcmp(tok3, "array")) + n->type = EET_G_ARRAY; + else if (!strcmp(tok3, "var_array")) + n->type = EET_G_VAR_ARRAY; + else if (!strcmp(tok3, "list")) + n->type = EET_G_LIST; + else if (!strcmp(tok3, "hash")) + n->type = EET_G_HASH; + else + ERR( + "ERROR: group type '%s' invalid.", + tok3); + + node = n; + } + } + + free(tok4); + } + + free(tok3); + } + + free(tok2); + } + } + else if (!strcmp(tok1, "value")) + { + TOK_GET(tok2); + if (tok2) + { + TOK_GET(tok3); + if (tok3) + { + TOK_GET(tok4); + if (tok4) + { +/* we have 'value NAME TYP XXX' */ + if (node_base) + { + n = eet_node_new(); + if (n) + { + n->parent = node; +/* append node */ + if (!node->values) + node->values = n; + else + for (nn = node->values; nn; + nn = nn->next) + { + if (!nn->next) + { + nn->next = n; + break; + } + } + + n->name = eina_stringshare_add(tok2); + if (!strcmp(tok3, "char:")) + { + n->type = EET_T_CHAR; + sscanf(tok4, "%hhi", + &(n->data.value.c)); + } + else if (!strcmp(tok3, "short:")) + { + n->type = EET_T_SHORT; + sscanf(tok4, "%hi", + &(n->data.value.s)); + } + else if (!strcmp(tok3, "int:")) + { + n->type = EET_T_INT; + sscanf(tok4, "%i", + &(n->data.value.i)); + } + else if (!strcmp(tok3, "long_long:")) + { + n->type = EET_T_LONG_LONG; + sscanf(tok4, "%lli", + &(n->data.value.l)); + } + else if (!strcmp(tok3, "float:")) + { + n->type = EET_T_FLOAT; + sscanf(tok4, "%f", + &(n->data.value.f)); + } + else if (!strcmp(tok3, "double:")) + { + n->type = EET_T_DOUBLE; + sscanf(tok4, "%lf", + &(n->data.value.d)); + } + else if (!strcmp(tok3, "uchar:")) + { + n->type = EET_T_UCHAR; + sscanf(tok4, "%hhu", + &(n->data.value.uc)); + } + else if (!strcmp(tok3, "ushort:")) + { + n->type = EET_T_USHORT; + sscanf(tok4, "%hu", + &(n->data.value.us)); + } + else if (!strcmp(tok3, "uint:")) + { + n->type = EET_T_UINT; + sscanf(tok4, "%u", + &(n->data.value.ui)); + } + else if (!strcmp(tok3, "ulong_long:")) + { + n->type = EET_T_ULONG_LONG; + sscanf(tok4, "%llu", + &(n->data.value.ul)); + } + else if (!strcmp(tok3, "string:")) + { + n->type = EET_T_STRING; + n->data.value.str = + eina_stringshare_add(tok4); + } + else if (!strcmp(tok3, "inlined:")) + { + n->type = EET_T_INLINED_STRING; + n->data.value.str = + eina_stringshare_add(tok4); + } + else if (!strcmp(tok3, "null")) + { + n->type = EET_T_NULL; + n->data.value.str = NULL; + } + else + ERR( + "ERROR: value type '%s' invalid.", + tok4); + } + } + + free(tok4); + } + + free(tok3); + } + + free(tok2); + } + } + else if (!strcmp(tok1, "key")) + { + TOK_GET(tok2); + if (tok2) + { +/* we have 'key NAME' */ + if (node) + node->key = eina_stringshare_add(tok2); + + free(tok2); + } + } + else if (!strcmp(tok1, "count")) + { + TOK_GET(tok2); + if (tok2) + { +/* we have a 'count COUNT' */ + if (node) + sscanf(tok2, "%i", &(node->count)); + + free(tok2); + } + } + else if (!strcmp(tok1, "}")) + /* we have an end of the group */ + if (node) + node = node->parent; + + free(tok1); + } } if (node_base) { - cdata = _eet_data_dump_encode(ed, node_base, size_ret); - _eet_data_dump_free(node_base); + cdata = _eet_data_dump_encode(EET_G_UNKNOWN, ed, node_base, size_ret); + eet_node_del(node_base); } + return cdata; } -#define NEXT_CHUNK(P, Size, Echnk, Ed) \ - { \ - int tmp; \ - tmp = Ed ? (int) (sizeof(int) * 2) : Echnk.len + 4;\ - P += (4 + Echnk.size + tmp); \ - Size -= (4 + Echnk.size + tmp); \ +#define NEXT_CHUNK(P, Size, Echnk, Ed) \ + { \ + int __tmp; \ + __tmp = Ed ? (int)(sizeof(int) * 2) : Echnk.len + 4; \ + P += (4 + Echnk.size + __tmp); \ + Size -= (4 + Echnk.size + __tmp); \ } static void * -_eet_data_descriptor_decode(const Eet_Dictionary *ed, - Eet_Data_Descriptor *edd, - const void *data_in, - int size_in, - int level, - void (*dumpfunc) (void *data, const char *str), - void *dumpdata) +_eet_data_descriptor_decode(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + const void *data_in, + int size_in, + void *data_out, + int size_out) { + Eet_Node *result = NULL; void *data = NULL; - char *p, *buf, tbuf[256]; - int size, i, dump; + char *p; + int size, i; Eet_Data_Chunk chnk; - if (words_bigendian == -1) + if (_eet_data_words_bigendian == -1) { - unsigned long int v; + unsigned long int v; - v = htonl(0x12345678); - if (v == 0x12345678) words_bigendian = 1; - else words_bigendian = 0; + v = htonl(0x12345678); + if (v == 0x12345678) + _eet_data_words_bigendian = 1; + else + _eet_data_words_bigendian = 0; } if (edd) { - data = edd->func.mem_alloc(edd->size); - if (!data) return NULL; - if (edd->ed != ed) - { - for (i = 0; i < edd->elements.num; i++) - edd->elements.set[i].directory_name_ptr = NULL; - edd->ed = ed; - } - } - _eet_freelist_ref(); - _eet_freelist_str_ref(); - _eet_freelist_list_ref(); - if (data) _eet_freelist_add(data); - dump = 0; + if (data_out) + { + if (size_out <= edd->size) + data = data_out; + } + else + { + data = edd->func.mem_alloc(edd->size); + } + + if (!data) + return NULL; + + if (edd->ed != ed) + { + for (i = 0; i < edd->elements.num; i++) + edd->elements.set[i].directory_name_ptr = NULL; + edd->ed = ed; + } + } + + _eet_freelist_all_ref(context); + if (data && !data_out) + _eet_freelist_add(context, data); + memset(&chnk, 0, sizeof(Eet_Data_Chunk)); eet_data_chunk_get(ed, &chnk, data_in, size_in); - if (!chnk.name) goto error; + if (!chnk.name) + goto error; + if (edd) - { - if (strcmp(chnk.name, edd->name)) goto error; - } + if (strcmp(chnk.name, edd->name)) + goto error; + p = chnk.data; if (ed) size = size_in - (4 + sizeof(int) * 2); else size = size_in - (4 + 4 + chnk.len); + if (edd) { - if (!edd->elements.hash.buckets) _eet_descriptor_hash_new(edd); - } - if (dumpfunc) - { - dump = 1; - if (chnk.type == EET_T_UNKNOW) - { - buf = tbuf; - - for (i = 0; i < level; i++) dumpfunc(dumpdata, " "); - dumpfunc(dumpdata, "group \""); - _eet_data_dump_string_escape(dumpdata, dumpfunc, chnk.name); - dumpfunc(dumpdata, "\" "); - switch (chnk.group_type) - { - case EET_G_UNKNOWN: - dumpfunc(dumpdata, "struct"); - break; - case EET_G_ARRAY: - dumpfunc(dumpdata, "array"); - break; - case EET_G_VAR_ARRAY: - dumpfunc(dumpdata, "var_array"); - break; - case EET_G_LIST: - dumpfunc(dumpdata, "list"); - break; - case EET_G_HASH: - dumpfunc(dumpdata, "hash"); - break; - default: - dumpfunc(dumpdata, "???"); - break; - } - dumpfunc(dumpdata, " {\n"); - } + if (!edd->elements.hash.buckets) + _eet_descriptor_hash_new(edd); + } + else + { + switch (chnk.group_type) + { + case EET_G_UNKNOWN: + switch (chnk.type) + { + case EET_T_STRING: + return eet_node_string_new(chnk.name, chnk.data); + + case EET_T_INLINED_STRING: + return eet_node_inlined_string_new(chnk.name, chnk.data); + + case EET_T_NULL: + return eet_node_null_new(chnk.name); + + default: + result = eet_node_struct_new(chnk.name, NULL); + } /* switch */ + break; + + case EET_G_VAR_ARRAY: + return eet_node_var_array_new(chnk.name, NULL); + + case EET_G_LIST: + case EET_G_HASH: + case EET_G_ARRAY: + case EET_G_UNION: + case EET_G_VARIANT: + default: + goto error; + } } + while (size > 0) { - Eet_Data_Chunk echnk; - Eet_Data_Element *ede; - - /* get next data chunk */ - memset(&echnk, 0, sizeof(Eet_Data_Chunk)); - eet_data_chunk_get(ed, &echnk, p, size); - if (!echnk.name) goto error; - /* FIXME: don't REPLY on edd - work without */ - if ((edd) && (!dumpfunc)) - { - ede = _eet_descriptor_hash_find(edd, echnk.name, echnk.hash); - if (ede) - { - int group_type = EET_G_UNKNOWN, type = EET_T_UNKNOW; - int ret = 0; - - group_type = ede->group_type; - type = ede->type; - if ((echnk.type == 0) && (echnk.group_type == 0)) - { - type = ede->type; - group_type = ede->group_type; - } - else - { - if (IS_SIMPLE_TYPE(echnk.type) && - (echnk.type == ede->type)) - type = echnk.type; - else if ((echnk.group_type > EET_G_UNKNOWN) && - (echnk.group_type < EET_G_LAST) && - (echnk.group_type == ede->group_type)) - group_type = echnk.group_type; - } - /* hashes doesnt fit well with the table */ - ret = eet_group_codec[group_type - 100].get(ed, edd, ede, &echnk, type, group_type, ((char *)data) + ede->offset, level, dumpfunc, dumpdata, &p, &size); - if (ret <= 0) goto error; - } - } - /*...... dump func */ - else if (dumpfunc) - { - unsigned char dd[128]; - int group_type = EET_G_UNKNOWN, type = EET_T_UNKNOW; - - if ((echnk.type > EET_T_UNKNOW) && - (echnk.type < EET_T_LAST)) - type = echnk.type; - else if ((echnk.group_type > EET_G_UNKNOWN) && - (echnk.group_type < EET_G_LAST)) - group_type = echnk.group_type; - if (group_type == EET_G_UNKNOWN) - { - int ret; - void *data_ret; - - if (IS_SIMPLE_TYPE(type)) - { - ret = eet_data_get_type(ed, - type, - echnk.data, - ((char *)echnk.data) + echnk.size, - dd); - for (i = 0; i < level; i++) dumpfunc(dumpdata, " "); - dumpfunc(dumpdata, " value \""); - _eet_data_dump_string_escape(dumpdata, dumpfunc, echnk.name); - dumpfunc(dumpdata, "\" "); - switch (type) - { - case EET_T_CHAR: - dumpfunc(dumpdata, "char: "); - snprintf(tbuf, sizeof(tbuf), "%hhi", *((char *)dd)); - dumpfunc(dumpdata, tbuf); break; - case EET_T_SHORT: - dumpfunc(dumpdata, "short: "); - snprintf(tbuf, sizeof(tbuf), "%hi", *((short *)dd)); - dumpfunc(dumpdata, tbuf); break; - case EET_T_INT: - dumpfunc(dumpdata, "int: "); - snprintf(tbuf, sizeof(tbuf), "%i", *((int *)dd)); - dumpfunc(dumpdata, tbuf); break; - case EET_T_LONG_LONG: - dumpfunc(dumpdata, "long_long: "); - snprintf(tbuf, sizeof(tbuf), "%lli", *((long long *)dd)); - dumpfunc(dumpdata, tbuf); break; - case EET_T_FLOAT: - dumpfunc(dumpdata, "float: "); - snprintf(tbuf, sizeof(tbuf), "%1.25f", *((float *)dd)); - dumpfunc(dumpdata, tbuf); break; - case EET_T_DOUBLE: - dumpfunc(dumpdata, "double: "); - snprintf(tbuf, sizeof(tbuf), "%1.25f", *((double *)dd)); - dumpfunc(dumpdata, tbuf); break; - case EET_T_UCHAR: - dumpfunc(dumpdata, "uchar: "); - snprintf(tbuf, sizeof(tbuf), "%hhu", *((unsigned char *)dd)); - dumpfunc(dumpdata, tbuf); break; - case EET_T_USHORT: - dumpfunc(dumpdata, "ushort: "); - snprintf(tbuf, sizeof(tbuf), "%i", *((unsigned short *)dd)); - dumpfunc(dumpdata, tbuf); break; - case EET_T_UINT: - dumpfunc(dumpdata, "uint: "); - snprintf(tbuf, sizeof(tbuf), "%u", *((unsigned int *)dd)); - dumpfunc(dumpdata, tbuf); break; - case EET_T_ULONG_LONG: - dumpfunc(dumpdata, "ulong_long: "); - snprintf(tbuf, sizeof(tbuf), "%llu", *((unsigned long long *)dd)); - dumpfunc(dumpdata, tbuf); break; - case EET_T_INLINED_STRING: - { - char *s; - - s = *((char **)dd); - if (s) - { - dumpfunc(dumpdata, "inlined: \""); - _eet_data_dump_string_escape(dumpdata, dumpfunc, s); - dumpfunc(dumpdata, "\""); - } - } - break; - case EET_T_STRING: - { - char *s; - - s = *((char **)dd); - if (s) - { - dumpfunc(dumpdata, "string: \""); - _eet_data_dump_string_escape(dumpdata, dumpfunc, s); - dumpfunc(dumpdata, "\""); - } - } - break; - default: - dumpfunc(dumpdata, "???: ???"); break; - break; - } - dumpfunc(dumpdata, ";\n"); - } - else - { - data_ret = _eet_data_descriptor_decode(ed, - NULL, - echnk.data, - echnk.size, - level + 1, - dumpfunc, - dumpdata); - if (!data_ret) goto error; - } - } - else - { - for (i = 0; i < level; i++) dumpfunc(dumpdata, " "); - dumpfunc(dumpdata, " group \""); - _eet_data_dump_string_escape(dumpdata, dumpfunc, echnk.name); - dumpfunc(dumpdata, "\" "); - switch (echnk.group_type) - { - case EET_G_UNKNOWN: - dumpfunc(dumpdata, "struct");break; - case EET_G_ARRAY: - dumpfunc(dumpdata, "array");break; - case EET_G_VAR_ARRAY: - dumpfunc(dumpdata, "var_array");break; - case EET_G_LIST: - dumpfunc(dumpdata, "list");break; - case EET_G_HASH: - dumpfunc(dumpdata, "hash");break; - default: - dumpfunc(dumpdata, "???");break; - break; - } - dumpfunc(dumpdata, " {\n"); - switch (group_type) - { - case EET_G_ARRAY: - case EET_G_VAR_ARRAY: - { - int count; - int ret; - int i; - - EET_ASSERT(!IS_SIMPLE_TYPE(type), goto error); - - ret = eet_data_get_type(ed, - EET_T_INT, - echnk.data, - ((char *)echnk.data) + echnk.size, - &count); - if (ret <= 0) goto error; - - for (i = 0; i < level; i++) dumpfunc(dumpdata, " "); - dumpfunc(dumpdata, " count "); - snprintf(tbuf, sizeof(tbuf), "%i", count); - dumpfunc(dumpdata, tbuf); - dumpfunc(dumpdata, ";\n"); - - /* get all array elements */ - for (i = 0; i < count; i++) - { - void *data_ret = NULL; - - /* Advance to next chunk */ - NEXT_CHUNK(p, size, echnk, ed); - memset(&echnk, 0, sizeof(Eet_Data_Chunk)); - - eet_data_chunk_get(ed, &echnk, p, size); - if (!echnk.name) goto error; - /* get the data */ - data_ret = _eet_data_descriptor_decode(ed, - NULL, - echnk.data, - echnk.size, - level + 2, - dumpfunc, - dumpdata); - if (!data_ret) goto error; - } - } - break; - case EET_G_LIST: - { - void *data_ret = NULL; - - EET_ASSERT(!IS_SIMPLE_TYPE(type), goto error); - - data_ret = _eet_data_descriptor_decode(ed, - NULL, - echnk.data, - echnk.size, - level + 2, - dumpfunc, - dumpdata); - if (!data_ret) goto error; - } - break; - case EET_G_HASH: - { - int ret; - char *key = NULL; - void *data_ret = NULL; - - /* Read key */ - ret = eet_data_get_type(ed, - EET_T_STRING, - echnk.data, - ((char *)echnk.data) + echnk.size, - &key); - if (ret <= 0) goto error; - - /* Advance to next chunk */ - NEXT_CHUNK(p, size, echnk, ed); - memset(&echnk, 0, sizeof(Eet_Data_Chunk)); - - /* Read value */ - eet_data_chunk_get(ed, &echnk, p, size); - if (!echnk.name) goto error; - - EET_ASSERT(!IS_SIMPLE_TYPE(type), goto error); - - { - char *s; - - s = key; - if (s) - { - for (i = 0; i < level; i++) dumpfunc(dumpdata, " "); - dumpfunc(dumpdata, " key \""); - _eet_data_dump_string_escape(dumpdata, dumpfunc, s); - dumpfunc(dumpdata, "\";\n"); - } - data_ret = _eet_data_descriptor_decode(ed, - NULL, - echnk.data, - echnk.size, - level + 2, - dumpfunc, - dumpdata); - } - if (!data_ret) - { - goto error; - } - } - break; - default: - break; - } - if (dumpfunc) - { - for (i = 0; i < level; i++) dumpfunc(dumpdata, " "); - dumpfunc(dumpdata, " }\n"); - } - } - } - /* advance to next chunk */ + Eet_Data_Chunk echnk; + Eet_Data_Element *ede = NULL; + Eet_Node *child = NULL; + int group_type = EET_G_UNKNOWN, type = EET_T_UNKNOW; + int ret = 0; + + /* get next data chunk */ + memset(&echnk, 0, sizeof(Eet_Data_Chunk)); + eet_data_chunk_get(ed, &echnk, p, size); + if (!echnk.name) + goto error; /* FIXME: don't REPLY on edd - work without */ + + if (edd) + { + ede = _eet_descriptor_hash_find(edd, echnk.name, echnk.hash); + if (ede) + { + group_type = ede->group_type; + type = ede->type; + if ((echnk.type == 0) && (echnk.group_type == 0)) + { + type = ede->type; + group_type = ede->group_type; + } + else + { + if (IS_SIMPLE_TYPE(echnk.type) && + eet_data_type_match(echnk.type, ede->type)) +/* Needed when converting on the fly from FP to Float */ + type = ede->type; + else if ((echnk.group_type > EET_G_UNKNOWN) && + (echnk.group_type < EET_G_LAST) && + (echnk.group_type == ede->group_type)) + group_type = echnk.group_type; + } + } + } + /*...... dump to node */ + else + { + type = echnk.type; + group_type = echnk.group_type; + } + + if (!edd && group_type == EET_G_UNKNOWN && IS_SIMPLE_TYPE(type)) + { + unsigned char dd[128]; + + ret = eet_data_get_type(ed, + type, + echnk.data, + ((char *)echnk.data) + echnk.size, + dd); + if (ret <= 0) + goto error; + + child = eet_data_node_simple_type(type, echnk.name, dd); + + eet_node_struct_append(result, echnk.name, child); + } + else + { + ret = eet_group_codec[group_type - 100].get( + context, + ed, + edd, + ede, + &echnk, + type, + group_type, + ede ? (void *)(((char *)data) + ede->offset) : (void **)&result, + &p, + &size); + + if (ret <= 0) + goto error; + } + + /* advance to next chunk */ NEXT_CHUNK(p, size, echnk, ed); } - _eet_freelist_unref(); - _eet_freelist_str_unref(); - _eet_freelist_list_unref(); - if (dumpfunc) + _eet_freelist_all_unref(context); + if (!edd) { - _eet_freelist_str_free(edd); - _eet_freelist_direct_str_free(edd); - _eet_freelist_list_free(edd); - _eet_freelist_free(edd); + _eet_freelist_str_free(context, edd); + _eet_freelist_direct_str_free(context, edd); + _eet_freelist_list_free(context, edd); + _eet_freelist_hash_free(context, edd); + _eet_freelist_array_free(context, edd); + _eet_freelist_free(context, edd); } else { - _eet_freelist_reset(); - _eet_freelist_str_reset(); - _eet_freelist_list_reset(); - } - if (dumpfunc) - { - if (dump) - { - if (chnk.type == EET_T_UNKNOW) - { - for (i = 0; i < level; i++) dumpfunc(dumpdata, " "); - dumpfunc(dumpdata, "}\n"); - } - } - return (void *)1; + _eet_freelist_reset(context); + _eet_freelist_str_reset(context); + _eet_freelist_list_reset(context); + _eet_freelist_hash_reset(context); + _eet_freelist_direct_str_reset(context); + _eet_freelist_array_reset(context); } + + if (!edd) + return result; + return data; error: - _eet_freelist_unref(); - _eet_freelist_str_unref(); - _eet_freelist_list_unref(); - _eet_freelist_str_free(edd); - _eet_freelist_direct_str_free(edd); - _eet_freelist_list_free(edd); - _eet_freelist_free(edd); - if (dumpfunc) - { - if (dump) - { - if (chnk.type == EET_T_UNKNOW) - { - for (i = 0; i < level; i++) dumpfunc(dumpdata, " "); - dumpfunc(dumpdata, "}\n"); - } - } - } + eet_node_del(result); + + _eet_freelist_all_unref(context); + _eet_freelist_str_free(context, edd); + _eet_freelist_direct_str_free(context, edd); + _eet_freelist_list_free(context, edd); + _eet_freelist_hash_free(context, edd); + _eet_freelist_array_free(context, edd); + _eet_freelist_free(context, edd); + + /* FIXME: Warn that something goes wrong here. */ return NULL; } static int -eet_data_get_list(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, - int type __UNUSED__, int group_type __UNUSED__, void *data, - int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, - char **p __UNUSED__, int *size __UNUSED__) +eet_data_get_list(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type, + int group_type __UNUSED__, + void *data, + char **p, + int *size) { + Eet_Data_Descriptor *subtype = NULL; void *list = NULL; void **ptr; void *data_ret; - EET_ASSERT(!IS_SIMPLE_TYPE(type), return 0); + EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0); + + if (ede) + { + subtype = ede->subtype; + + if (type != ede->type) + return 0; + } ptr = (void **)data; list = *ptr; data_ret = NULL; - data_ret = _eet_data_descriptor_decode(ed, ede->subtype, echnk->data, echnk->size, level + 2, dumpfunc, dumpdata); - if (!data_ret) return 0; + if (IS_POINTER_TYPE(type)) + POINTER_TYPE_DECODE(context, + ed, + edd, + ede, + echnk, + type, + &data_ret, + p, + size, + on_error); + else + STRUCT_TYPE_DECODE(data_ret, + context, + ed, + subtype, + echnk->data, + echnk->size, + -1, + on_error); - list = edd->func.list_append(list, data_ret); - *ptr = list; - _eet_freelist_list_add(ptr); + if (edd) + { + list = edd->func.list_append(list, data_ret); + *ptr = list; + _eet_freelist_list_add(context, ptr); + } + else + eet_node_list_append(*((Eet_Node **)data), echnk->name, data_ret); return 1; + +on_error: + return 0; } static int -eet_data_get_hash(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, - int type, int group_type __UNUSED__, void *data, - int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, - char **p, int *size) +eet_data_get_hash(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type, + int group_type __UNUSED__, + void *data, + char **p, + int *size) { void **ptr; void *hash = NULL; @@ -2580,18 +3584,22 @@ eet_data_get_hash(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_E void *data_ret = NULL; int ret = 0; - EET_ASSERT(!IS_SIMPLE_TYPE(type), return 0); + EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0); ptr = (void **)data; hash = *ptr; /* Read key */ ret = eet_data_get_type(ed, - EET_T_STRING, - echnk->data, - ((char *)echnk->data) + echnk->size, - &key); - if (ret <= 0) goto on_error; + EET_T_STRING, + echnk->data, + ((char *)echnk->data) + echnk->size, + &key); + if (ret <= 0) + goto on_error; + + if (!key) + goto on_error; /* Advance to next chunk */ NEXT_CHUNK((*p), (*size), (*echnk), ed); @@ -2599,24 +3607,48 @@ eet_data_get_hash(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_E /* Read value */ eet_data_chunk_get(ed, echnk, *p, *size); - if (!echnk->name) goto on_error; - - data_ret = _eet_data_descriptor_decode(ed, - ede->subtype, - echnk->data, - echnk->size, - level + 2, - dumpfunc, - dumpdata); - if (!data_ret) goto on_error; - - hash = edd->func.hash_add(hash, key, data_ret); - *ptr = hash; - _eet_freelist_list_add(ptr); + if (!echnk->name) + goto on_error; + + if (ede) + if ((ede->group_type != echnk->group_type) + || (ede->type != echnk->type)) + goto on_error; + + if (IS_POINTER_TYPE(echnk->type)) + POINTER_TYPE_DECODE(context, + ed, + edd, + ede, + echnk, + echnk->type, + &data_ret, + p, + size, + on_error); + else + STRUCT_TYPE_DECODE(data_ret, + context, + ed, + ede ? ede->subtype : NULL, + echnk->data, + echnk->size, + -1, + on_error); + + if (edd) + { + hash = edd->func.hash_add(hash, key, data_ret); + *ptr = hash; + _eet_freelist_hash_add(context, hash); + } + else + eet_node_hash_add(*((Eet_Node **)data), echnk->name, key, data_ret); + return 1; - on_error: - return ret; +on_error: + return 0; } /* var arrays and fixed arrays have to @@ -2630,181 +3662,814 @@ eet_data_get_hash(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_E * each chunk is pointless. */ static int -eet_data_get_array(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd __UNUSED__, - Eet_Data_Element *ede, Eet_Data_Chunk *echnk, - int type, int group_type, void *data, - int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, - char **p, int *size) +eet_data_get_array(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type, + int group_type, + void *data, + char **p, + int *size) { + Eina_List *childs = NULL; + const char *name; + Eet_Node *tmp; void *ptr; int count; int ret; + int subsize = 0; int i; - EET_ASSERT(!IS_SIMPLE_TYPE(type), return 0); + EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0); ptr = data; /* read the number of elements */ ret = eet_data_get_type(ed, - EET_T_INT, - echnk->data, - ((char *)echnk->data) + echnk->size, - &count); - if (ret <= 0) return ret; - if (group_type == EET_G_VAR_ARRAY) - { - /* store the number of elements - * on the counter offset */ - *(int *)(((char *)data) + ede->count - ede->offset) = count; - /* allocate space for the array of elements */ - *(void **)ptr = calloc(count, ede->subtype->size); + EET_T_INT, + echnk->data, + ((char *)echnk->data) + echnk->size, + &count); + if (ret <= 0) + return ret; - if (!*(void **)ptr) return 0; + name = echnk->name; - _eet_freelist_add(*(void **)ptr); + if (ede) + { + if (IS_POINTER_TYPE(type)) + subsize = eet_basic_codec[ede->type - 1].size; + else + subsize = ede->subtype->size; + + if (group_type == EET_G_VAR_ARRAY) + { + /* store the number of elements + * on the counter offset */ + *(int *)(((char *)data) + ede->count - ede->offset) = count; + /* allocate space for the array of elements */ + if (edd->func.array_alloc) + *(void **)ptr = edd->func.array_alloc(count * subsize); + else + *(void **)ptr = edd->func.mem_alloc(count * subsize); + + if (!*(void **)ptr) + return 0; + + memset(*(void **)ptr, 0, count * subsize); + + _eet_freelist_array_add(context, *(void **)ptr); + } } /* get all array elements */ for (i = 0; i < count; i++) { - void *dst; - void *data_ret = NULL; - - /* Advance to next chunk */ - NEXT_CHUNK((*p), (*size), (*echnk), ed); - memset(echnk, 0, sizeof(Eet_Data_Chunk)); - - eet_data_chunk_get(ed, echnk, *p, *size); - if (!echnk->name) return 0; - /* get the data */ - - /* get the destination pointer */ - if (group_type == EET_G_ARRAY) - dst = (char *)ptr + (ede->subtype->size * i); - else - dst = *(char **)ptr + (ede->subtype->size * i); - data_ret = _eet_data_descriptor_decode(ed, - ede->subtype, - echnk->data, - echnk->size, - level + 2, - dumpfunc, - dumpdata); - if (!data_ret) return 0; - memcpy(dst, data_ret, ede->subtype->size); - free(data_ret); + void *dst = NULL; + + /* Advance to next chunk */ + NEXT_CHUNK((*p), (*size), (*echnk), ed); + memset(echnk, 0, sizeof(Eet_Data_Chunk)); + + eet_data_chunk_get(ed, echnk, *p, *size); + if (!echnk->name || strcmp(echnk->name, name) != 0) + goto on_error; /* get the data */ + + if ((echnk->group_type != group_type) + || ((echnk->type != type) && (echnk->type != EET_T_NULL))) + goto on_error; + + if (ede) + if ((ede->group_type != echnk->group_type) + || ((echnk->type != ede->type) && (echnk->type != EET_T_NULL))) + goto on_error; + + /* get the destination pointer */ + if (ede) + { + if (group_type == EET_G_ARRAY) + dst = (char *)ptr + (subsize * i); + else + dst = *(char **)ptr + (subsize * i); + } + + if (IS_POINTER_TYPE(echnk->type)) + { + void *data_ret = NULL; + + POINTER_TYPE_DECODE(context, + ed, + edd, + ede, + echnk, + echnk->type, + &data_ret, + p, + size, + on_error); + if (dst) + memcpy(dst, &data_ret, subsize); + + if (!edd) + childs = eina_list_append(childs, data_ret); + } + else + { + STRUCT_TYPE_DECODE(dst, + context, + ed, + ede ? ede->subtype : NULL, + echnk->data, + echnk->size, + subsize, + on_error); + + if (!edd) + childs = eina_list_append(childs, dst); + } } + + if (!edd) + { + Eet_Node *parent = *((Eet_Node **)data); + Eet_Node *array; + + if (group_type == EET_G_ARRAY) + array = eet_node_array_new(name, count, childs); + else + array = eet_node_var_array_new(name, childs); + + if (!array) + goto on_error; + + eet_node_struct_append(parent, name, array); + } + return 1; + +on_error: + EINA_LIST_FREE(childs, tmp) + eet_node_del(tmp); + + return 0; +} + +static void +eet_data_put_union(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd __UNUSED__, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in) +{ + const char *union_type; + int i; + + EET_ASSERT(!((ede->type != EET_T_UNKNOW) || (!ede->subtype)), return ); + + union_type = ede->subtype->func.type_get( + ((char *)data_in) + ede->count - ede->offset, + NULL); + + if (!union_type) + return; + + /* Search the structure of the union to encode. */ + for (i = 0; i < ede->subtype->elements.num; ++i) + if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0) + { + Eet_Data_Element *sede; + void *data; + int size; + + /* Yeah we found it ! */ + data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size); + if (data) + eet_data_encode(ed, + ds, + data, + ede->name, + size, + ede->type, + ede->group_type); + + sede = &(ede->subtype->elements.set[i]); + data = _eet_data_descriptor_encode(ed, + sede->subtype, + data_in, + &size); + if (data) + eet_data_encode(ed, + ds, + data, + ede->name, + size, + ede->type, + ede->group_type); + + break; + } } static int -eet_data_get_unknown(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, - int type, int group_type __UNUSED__, void *data, - int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, - char **p __UNUSED__, int *size __UNUSED__) +eet_data_get_union(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd __UNUSED__, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type, + int group_type, + void *data, + char **p, + int *size) { - int ret; - void *data_ret; + const char *union_type; + void *data_ret = NULL; + int ret = 0; + int i; - if (IS_SIMPLE_TYPE(type)) + /* Read type */ + ret = eet_data_get_type(ed, + EET_T_STRING, + echnk->data, + ((char *)echnk->data) + echnk->size, + &union_type); + if (ret <= 0) + goto on_error; + + /* Advance to next chunk */ + NEXT_CHUNK((*p), (*size), (*echnk), ed); + memset(echnk, 0, sizeof(Eet_Data_Chunk)); + + /* Read value */ + eet_data_chunk_get(ed, echnk, *p, *size); + if (!echnk->name) + goto on_error; + + if (ede) { - ret = eet_data_get_type(ed, type, echnk->data, ((char *)echnk->data) + echnk->size, ((char *)data)); - if (ret <= 0) return ret; - - if (type == EET_T_STRING) - { - char **str; - - str = (char **)(((char *)data)); - if (*str) - { - if ((ed == NULL) || (edd->func.str_direct_alloc == NULL)) - { - *str = edd->func.str_alloc(*str); - _eet_freelist_str_add(*str); - } - else - { - *str = edd->func.str_direct_alloc(*str); - _eet_freelist_direct_str_add(*str); - } - } - } - else if (type == EET_T_INLINED_STRING) - { - char **str; - - str = (char **)(((char *)data)); - if (*str) - { - *str = edd->func.str_alloc(*str); - _eet_freelist_str_add(*str); - } - } + EET_ASSERT(!(ede->group_type != group_type || ede->type != type), + goto on_error); + + /* Search the structure of the union to decode */ + for (i = 0; i < ede->subtype->elements.num; ++i) + if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0) + { + Eet_Data_Element *sede; + char *ut; + + /* Yeah we found it ! */ + sede = &(ede->subtype->elements.set[i]); + EET_ASSERT(sede->subtype, goto on_error); + + data_ret = _eet_data_descriptor_decode(context, + ed, + sede->subtype, + echnk->data, + echnk->size, + data, + sede->subtype->size); + if (!data_ret) + goto on_error; + + /* Set union type. */ + if ((!ed) || (!ede->subtype->func.str_direct_alloc)) + { + ut = ede->subtype->func.str_alloc(union_type); + _eet_freelist_str_add(context, ut); + } + else + { + ut = ede->subtype->func.str_direct_alloc(union_type); + _eet_freelist_direct_str_add(context, ut); + } + + ede->subtype->func.type_set( + ut, + ((char *)data) + ede->count - + ede->offset, + EINA_FALSE); + + break; + } } - else if (ede->subtype) + else { - void **ptr; + /* FIXME: generate node structure. */ + data_ret = _eet_data_descriptor_decode(context, + ed, NULL, + echnk->data, echnk->size, + NULL, 0); + goto on_error; + } - data_ret = _eet_data_descriptor_decode(ed, ede->subtype, echnk->data, echnk->size, level + 1, dumpfunc, dumpdata); - if (!data_ret) return 0; + return 1; - ptr = (void **)(((char *)data)); - *ptr = (void *)data_ret; +on_error: + return 0; +} + +static void +eet_data_put_variant(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd __UNUSED__, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in) +{ + const char *union_type; + void *data; + Eina_Bool unknow = EINA_FALSE; + int size; + int i; + + EET_ASSERT(!((ede->type != EET_T_UNKNOW) || (!ede->subtype)), return ); + + union_type = ede->subtype->func.type_get( + ((char *)data_in) + ede->count - ede->offset, + &unknow); + + if (!union_type && unknow == EINA_FALSE) + return; + + if (unknow) + { + /* Handle opaque internal representation */ + Eet_Variant_Unknow *evu; + + data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size); + if (data) + eet_data_encode(ed, + ds, + data, + ede->name, + size, + ede->type, + ede->group_type); + + evu = (Eet_Variant_Unknow *)data_in; + if (evu && EINA_MAGIC_CHECK(evu, EET_MAGIC_VARIANT)) + eet_data_encode(ed, + ds, + evu->data, + ede->name, + evu->size, + ede->type, + ede->group_type); + } + else + /* Search the structure of the union to encode. */ + for (i = 0; i < ede->subtype->elements.num; ++i) + if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0) + { + Eet_Data_Element *sede; + + /* Yeah we found it ! */ + data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size); + if (data) + eet_data_encode(ed, + ds, + data, + ede->name, + size, + ede->type, + ede->group_type); + + sede = &(ede->subtype->elements.set[i]); + + if (sede->group_type != EET_G_UNKNOWN) + { + Eet_Data_Stream *lds; + + lds = eet_data_stream_new(); + eet_group_codec[sede->group_type - 100].put(ed, + sede->subtype, + sede, + lds, + data_in); + if (lds->size != 0) + { + eet_data_encode(ed, ds, lds->data, ede->name, lds->pos, + ede->type, ede->group_type); + + lds->data = NULL; + lds->size = 0; + } + else + eet_data_encode(ed, ds, NULL, ede->name, 0, + EET_T_NULL, ede->group_type); + + eet_data_stream_free(lds); + } + else + { + data = _eet_data_descriptor_encode(ed, + sede->subtype, + *(void **)data_in, + &size); + if (data) + eet_data_encode(ed, + ds, + data, + ede->name, + size, + ede->type, + ede->group_type); + } + + break; + } +} + +static int +eet_data_get_variant(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd __UNUSED__, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type __UNUSED__, + int group_type __UNUSED__, + void *data, + char **p, + int *size) +{ + const char *union_type; + void *data_ret = NULL; + int ret = 0; + int i; + + /* Read type */ + ret = eet_data_get_type(ed, + EET_T_STRING, + echnk->data, + ((char *)echnk->data) + echnk->size, + &union_type); + if (ret <= 0) + goto on_error; + + /* Advance to next chunk */ + NEXT_CHUNK((*p), (*size), (*echnk), ed); + memset(echnk, 0, sizeof(Eet_Data_Chunk)); + + /* Read value */ + eet_data_chunk_get(ed, echnk, *p, *size); + if (!echnk->name) + goto on_error; + + if (ede) + { + char *ut; + + EET_ASSERT(ede->subtype, goto on_error); + + if ((!ed) || (!ede->subtype->func.str_direct_alloc)) + { + ut = ede->subtype->func.str_alloc(union_type); + _eet_freelist_str_add(context, ut); + } + else + { + ut = ede->subtype->func.str_direct_alloc(union_type); + _eet_freelist_direct_str_add(context, ut); + } + + /* Search the structure of the union to decode */ + for (i = 0; i < ede->subtype->elements.num; ++i) + if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0) + { + Eet_Data_Element *sede; + + /* Yeah we found it ! */ + sede = &(ede->subtype->elements.set[i]); + + if (sede->group_type != EET_G_UNKNOWN) + { + Eet_Data_Chunk chnk; + char *p2; + int size2; + + p2 = echnk->data; + size2 = echnk->size; + + /* Didn't find a proper way to provide this + without duplicating code */ + while (size2 > 0) + { + memset(&chnk, 0, sizeof(Eet_Data_Chunk)); + eet_data_chunk_get(ed, &chnk, p2, size2); + + if (!chnk.name) + goto on_error; + + ret = eet_group_codec[sede->group_type - 100].get + (context, ed, sede->subtype, sede, &chnk, sede->type, + sede->group_type, data, &p2, &size2); + + if (ret <= 0) + goto on_error; + +/* advance to next chunk */ + NEXT_CHUNK(p2, size2, chnk, ed); + } + + /* Put garbage so that we will not put eet_variant_unknow in it */ + data_ret = (void *)data; + + /* Set variant type. */ + ede->subtype->func.type_set + (ut, ((char *)data) + ede->count - ede->offset, + EINA_FALSE); + break; + } + + data_ret = _eet_data_descriptor_decode(context, + ed, + sede->subtype, + echnk->data, + echnk->size, + NULL, 0); + if (!data_ret) + break; + + /* And point to the variant data. */ + *(void **)data = data_ret; + + /* Set variant type. */ + ede->subtype->func.type_set + (ut, ((char *)data) + ede->count - ede->offset, EINA_FALSE); + break; + } + + if (!data_ret) + { + Eet_Variant_Unknow *evu; + + evu = calloc(1, sizeof (Eet_Variant_Unknow) + echnk->size - 1); + if (!evu) + goto on_error; + + evu->size = echnk->size; + memcpy(evu->data, echnk->data, evu->size); + EINA_MAGIC_SET(evu, EET_MAGIC_VARIANT); + + /* And point to the opaque internal data scructure */ + *(void **)data = evu; + + /* Set variant type. */ + ede->subtype->func.type_set + (ut, ((char *)data) + ede->count - ede->offset, EINA_TRUE); + } + } + else + { + /* FIXME: dump node structure. */ + data_ret = _eet_data_descriptor_decode(context, + ed, NULL, + echnk->data, echnk->size, + NULL, 0); + goto on_error; } return 1; + +on_error: + return 0; } -static void -eet_data_encode(Eet_Dictionary *ed, Eet_Data_Stream *ds, void *data, const char *name, int size, int type, int group_type) +static Eet_Node * +eet_data_node_simple_type(int type, + const char *name, + void *dd) { - Eet_Data_Chunk *echnk; +#ifdef EET_T_TYPE +# undef EET_T_TYPE +#endif /* ifdef EET_T_TYPE */ - echnk = eet_data_chunk_new(data, size, name, type, group_type); - eet_data_chunk_put(ed, echnk, ds); - eet_data_chunk_free(echnk); - free(data); +#define EET_T_TYPE(Eet_Type, Eet_Node_Type, Type) \ +case Eet_Type: \ + return eet_node_ ## Eet_Node_Type ## _new(name, *((Type *)dd)); \ + + switch (type) + { + EET_T_TYPE(EET_T_CHAR, char, char); + EET_T_TYPE(EET_T_SHORT, short, short); + EET_T_TYPE(EET_T_INT, int, int); + EET_T_TYPE(EET_T_LONG_LONG, long_long, long long); + EET_T_TYPE(EET_T_FLOAT, float, float); + EET_T_TYPE(EET_T_DOUBLE, double, double); + EET_T_TYPE(EET_T_UCHAR, unsigned_char, unsigned char); + EET_T_TYPE(EET_T_USHORT, unsigned_short, unsigned short); + EET_T_TYPE(EET_T_UINT, unsigned_int, unsigned int); + EET_T_TYPE(EET_T_ULONG_LONG, unsigned_long_long, unsigned long long); + EET_T_TYPE(EET_T_STRING, string, char *); + EET_T_TYPE(EET_T_INLINED_STRING, inlined_string, char *); + + case EET_T_NULL: + return eet_node_null_new(name); + + default: + ERR("Unknow type passed to eet_data_node_simple_type"); + return NULL; + } +} + +static int +eet_data_get_unknown(Eet_Free_Context *context, + const Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Chunk *echnk, + int type, + int group_type __UNUSED__, + void *data, + char **p __UNUSED__, + int *size __UNUSED__) +{ + int ret; + void *data_ret; + + if (IS_SIMPLE_TYPE(type)) + { + unsigned char dd[128]; + + ret = eet_data_get_type(ed, + type, + echnk->data, + ((char *)echnk->data) + echnk->size, + edd ? (char *)data : (char *)dd); + if (ret <= 0) + return ret; + + if (!edd) + { + Eet_Node **parent = data; + Eet_Node *node; + + node = eet_data_node_simple_type(type, echnk->name, dd); + + if (*parent) + eet_node_struct_append(*parent, echnk->name, node); + else + *parent = node; + } + else + { + if (type == EET_T_STRING) + { + char **str; + + str = (char **)(((char *)data)); + if (*str) + { + if ((!ed) || (!edd->func.str_direct_alloc)) + { + *str = edd->func.str_alloc(*str); + _eet_freelist_str_add(context, *str); + } + else + { + *str = edd->func.str_direct_alloc(*str); + _eet_freelist_direct_str_add(context, *str); + } + } + } + else if (edd && type == EET_T_INLINED_STRING) + { + char **str; + + str = (char **)(((char *)data)); + if (*str) + { + *str = edd->func.str_alloc(*str); + _eet_freelist_str_add(context, *str); + } + } + } + } + else + { + Eet_Data_Descriptor *subtype; + + subtype = ede ? ede->subtype : NULL; + + if (subtype || !edd) + { + Eet_Node **parent = data; + void **ptr; + + data_ret = _eet_data_descriptor_decode(context, + ed, + subtype, + echnk->data, + echnk->size, + NULL, 0); + if (!data_ret) + return 0; + + if (edd) + { + ptr = (void **)(((char *)data)); + *ptr = (void *)data_ret; + } + else + { + Eet_Node *node = data_ret; + + if (*parent) + { + node = eet_node_struct_child_new(echnk->name, node); + eet_node_struct_append(*parent, echnk->name, node); + } + else + *parent = node; + } + } + } + + return 1; } static void -eet_data_put_array(Eet_Dictionary *ed, Eet_Data_Descriptor *edd __UNUSED__, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in) +eet_data_put_array(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd __UNUSED__, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in) { void *data; - int size; - int j; int offset = 0; + int subsize; int count; + int size; + int j; - EET_ASSERT(!IS_SIMPLE_TYPE(ede->type), return ); + EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)), + return ); if (ede->group_type == EET_G_ARRAY) count = ede->counter_offset; else count = *(int *)(((char *)data_in) + ede->count - ede->offset); - if (count <= 0) return; - /* Store number of elements */ + if (count <= 0) + return; /* Store number of elements */ + data = eet_data_put_type(ed, EET_T_INT, &count, &size); - if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type); + if (data) + eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type); + + if (IS_POINTER_TYPE(ede->type)) + subsize = eet_basic_codec[ede->type - 1].size; + else + subsize = ede->subtype->size; for (j = 0; j < count; j++) { - void *d; - - if (ede->group_type == EET_G_ARRAY) - d = (void *)(((char *)data_in) + offset); - else - d = *(((char **)data_in)) + offset; - - data = _eet_data_descriptor_encode(ed, ede->subtype, d, &size); - offset += ede->subtype->size; - if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type); + void *d; + int pos = ds->pos; + + if (ede->group_type == EET_G_ARRAY) + d = (void *)(((char *)data_in) + offset); + else + d = *(((char **)data_in)) + offset; + + if (IS_POINTER_TYPE(ede->type)) + { + if (*(char **)d) + eet_data_put_unknown(ed, NULL, ede, ds, d); + } + else + { + data = _eet_data_descriptor_encode(ed, ede->subtype, d, &size); + if (data) + eet_data_encode(ed, + ds, + data, + ede->name, + size, + ede->type, + ede->group_type); + } + + if (pos == ds->pos) + /* Add a NULL element just to have the correct array layout. */ + eet_data_encode(ed, + ds, + NULL, + ede->name, + 0, + EET_T_NULL, + ede->group_type); + + offset += subsize; } } static void -eet_data_put_unknown(Eet_Dictionary *ed, Eet_Data_Descriptor *edd __UNUSED__, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in) +eet_data_put_unknown(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd __UNUSED__, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in) { void *data = NULL; int size; @@ -2812,38 +4477,69 @@ eet_data_put_unknown(Eet_Dictionary *ed, Eet_Data_Descriptor *edd __UNUSED__, Ee if (IS_SIMPLE_TYPE(ede->type)) data = eet_data_put_type(ed, ede->type, data_in, &size); else if (ede->subtype) - { - if (*((char **)data_in)) - data = _eet_data_descriptor_encode(ed, - ede->subtype, - *((char **)((char *)(data_in))), - &size); - } - if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type); + if (*((char **)data_in)) + data = _eet_data_descriptor_encode(ed, + ede->subtype, + *((char **)((char *)(data_in))), + &size); + + if (data) + eet_data_encode(ed, + ds, + data, + ede->name, + size, + ede->type, + ede->group_type); } static void -eet_data_put_list(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in) +eet_data_put_list(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in) { void *data; void *l; int size; - EET_ASSERT(!IS_SIMPLE_TYPE(ede->type), return ); + EET_ASSERT(!(((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)) + || ((ede->type > EET_T_NULL) && (ede->type < EET_T_LAST))), + return ); l = *((void **)(((char *)data_in))); for (; l; l = edd->func.list_next(l)) { - data = _eet_data_descriptor_encode(ed, - ede->subtype, - edd->func.list_data(l), - &size); - if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type); + if (IS_POINTER_TYPE(ede->type)) + { + const void *str = edd->func.list_data(l); + eet_data_put_unknown(ed, NULL, ede, ds, &str); + } + else + { + data = _eet_data_descriptor_encode(ed, + ede->subtype, + edd->func.list_data(l), + &size); + if (data) + eet_data_encode(ed, + ds, + data, + ede->name, + size, + ede->type, + ede->group_type); + } } } static void -eet_data_put_hash(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in) +eet_data_put_hash(Eet_Dictionary *ed, + Eet_Data_Descriptor *edd, + Eet_Data_Element *ede, + Eet_Data_Stream *ds, + void *data_in) { Eet_Data_Encode_Hash_Info fdata; void *l; @@ -2856,118 +4552,307 @@ eet_data_put_hash(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element } EAPI int -eet_data_dump(Eet_File *ef, - const char *name, - void (*dumpfunc) (void *data, const char *str), - void *dumpdata) +eet_data_dump_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + Eet_Dump_Callback dumpfunc, + void *dumpdata) { const Eet_Dictionary *ed = NULL; - const void *data; - int ret = 0; - int required_free = 0; - int size; + const void *data = NULL; + Eet_Node *result; + Eet_Free_Context context; + int required_free = 0; + int size; ed = eet_dictionary_get(ef); - data = eet_read_direct(ef, name, &size); + if (!cipher_key) + data = eet_read_direct(ef, name, &size); + if (!data) { - required_free = 1; - data = eet_read(ef, name, &size); - if (!data) return 0; + required_free = 1; + data = eet_read_cipher(ef, name, &size, cipher_key); + if (!data) + return 0; } - if (_eet_data_descriptor_decode(ed, NULL, data, size, 0, - dumpfunc, dumpdata)) - ret = 1; + eet_free_context_init(&context); + result = _eet_data_descriptor_decode(&context, ed, NULL, data, size, NULL, 0); + eet_free_context_shutdown(&context); + + eet_node_dump(result, 0, dumpfunc, dumpdata); + + eet_node_del(result); if (required_free) - free((void*)data); + free((void *)data); - return ret; + return result ? 1 : 0; } +EAPI int +eet_data_dump(Eet_File *ef, + const char *name, + Eet_Dump_Callback dumpfunc, + void *dumpdata) +{ + return eet_data_dump_cipher(ef, name, NULL, dumpfunc, dumpdata); +} EAPI int -eet_data_text_dump(const void *data_in, - int size_in, - void (*dumpfunc) (void *data, const char *str), - void *dumpdata) -{ - if (_eet_data_descriptor_decode(NULL, NULL, data_in, size_in, 0, - dumpfunc, dumpdata)) - return 1; - return 0; +eet_data_text_dump_cipher(const void *data_in, + const char *cipher_key, + int size_in, + Eet_Dump_Callback dumpfunc, + void *dumpdata) +{ + void *ret = NULL; + Eet_Node *result; + Eet_Free_Context context; + unsigned int ret_len = 0; + + if (!data_in) + return 0; + + if (cipher_key) + { + if (eet_decipher(data_in, size_in, cipher_key, + strlen(cipher_key), &ret, &ret_len)) + { + if (ret) + free(ret); + + return 0; + } + } + else + { + ret = (void *)data_in; + ret_len = size_in; + } + + eet_free_context_init(&context); + result = _eet_data_descriptor_decode(&context, NULL, NULL, ret, ret_len, NULL, 0); + eet_free_context_shutdown(&context); + + eet_node_dump(result, 0, dumpfunc, dumpdata); + + eet_node_del(result); + if (cipher_key) + free(ret); + + return result ? 1 : 0; +} + +EAPI int +eet_data_text_dump(const void *data_in, + int size_in, + Eet_Dump_Callback dumpfunc, + void *dumpdata) +{ + return eet_data_text_dump_cipher(data_in, NULL, size_in, dumpfunc, dumpdata); +} + +EAPI void * +eet_data_text_undump_cipher(const char *text, + const char *cipher_key, + int textlen, + int *size_ret) +{ + void *ret = NULL; + + ret = _eet_data_dump_parse(NULL, size_ret, text, textlen); + if (ret && cipher_key) + { + void *ciphered = NULL; + unsigned int ciphered_len; + + if (eet_cipher(ret, *size_ret, cipher_key, + strlen(cipher_key), &ciphered, &ciphered_len)) + { + if (ciphered) + free(ciphered); + + size_ret = 0; + free(ret); + return NULL; + } + + free(ret); + *size_ret = ciphered_len; + ret = ciphered; + } + + return ret; } EAPI void * eet_data_text_undump(const char *text, - int textlen, - int *size_ret) + int textlen, + int *size_ret) { - return _eet_data_dump_parse(NULL, size_ret, text, textlen); + return eet_data_text_undump_cipher(text, NULL, textlen, size_ret); } EAPI int -eet_data_undump(Eet_File *ef, - const char *name, - const char *text, - int textlen, - int compress) -{ - Eet_Dictionary *ed; - void *data_enc; - int size; - int val; +eet_data_undump_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + const char *text, + int textlen, + int comp) +{ + Eet_Dictionary *ed; + void *data_enc; + int size; + int val; ed = eet_dictionary_get(ef); data_enc = _eet_data_dump_parse(ed, &size, text, textlen); - if (!data_enc) return 0; - val = eet_write(ef, name, data_enc, size, compress); + if (!data_enc) + return 0; + + val = eet_write_cipher(ef, name, data_enc, size, comp, cipher_key); free(data_enc); return val; } +EAPI int +eet_data_undump(Eet_File *ef, + const char *name, + const char *text, + int textlen, + int comp) +{ + return eet_data_undump_cipher(ef, name, NULL, text, textlen, comp); +} + +EAPI void * +eet_data_descriptor_decode_cipher(Eet_Data_Descriptor *edd, + const void *data_in, + const char *cipher_key, + int size_in) +{ + void *deciphered = (void *)data_in; + void *ret; + Eet_Free_Context context; + unsigned int deciphered_len = size_in; + + EINA_SAFETY_ON_NULL_RETURN_VAL(edd, NULL); + + if (cipher_key && data_in) + if (eet_decipher(data_in, size_in, cipher_key, + strlen(cipher_key), &deciphered, &deciphered_len)) + { + if (deciphered) + free(deciphered); + + return NULL; + } + + eet_free_context_init(&context); + ret = _eet_data_descriptor_decode(&context, + NULL, + edd, + deciphered, + deciphered_len, + NULL, 0); + eet_free_context_shutdown(&context); + + if (data_in != deciphered) + free(deciphered); + + return ret; +} + EAPI void * eet_data_descriptor_decode(Eet_Data_Descriptor *edd, - const void *data_in, - int size_in) + const void *data_in, + int size_in) { - return _eet_data_descriptor_decode(NULL, edd, data_in, size_in, 0, - NULL, NULL); + return eet_data_descriptor_decode_cipher(edd, data_in, NULL, size_in); +} + +EAPI Eet_Node * +eet_data_node_decode_cipher(const void *data_in, + const char *cipher_key, + int size_in) +{ + void *deciphered = (void *)data_in; + Eet_Node *ret; + Eet_Free_Context context; + unsigned int deciphered_len = size_in; + + if (cipher_key && data_in) + if (eet_decipher(data_in, size_in, cipher_key, + strlen(cipher_key), &deciphered, &deciphered_len)) + { + if (deciphered) + free(deciphered); + + return NULL; + } + + eet_free_context_init(&context); + ret = _eet_data_descriptor_decode(&context, + NULL, + NULL, + deciphered, + deciphered_len, + NULL, 0); + eet_free_context_shutdown(&context); + + if (data_in != deciphered) + free(deciphered); + + return ret; } static void * -_eet_data_descriptor_encode(Eet_Dictionary *ed, +_eet_data_descriptor_encode(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, - const void *data_in, - int *size_ret) + const void *data_in, + int *size_ret) { - Eet_Data_Stream *ds; - Eet_Data_Chunk *chnk; - void *cdata; - int csize; - int i; + Eet_Data_Stream *ds; + Eet_Data_Chunk *chnk; + void *cdata; + int csize; + int i; - if (words_bigendian == -1) + if (_eet_data_words_bigendian == -1) { - unsigned long int v; + unsigned long int v; - v = htonl(0x12345678); - if (v == 0x12345678) words_bigendian = 1; - else words_bigendian = 0; + v = htonl(0x12345678); + if (v == 0x12345678) + _eet_data_words_bigendian = 1; + else + _eet_data_words_bigendian = 0; } ds = eet_data_stream_new(); for (i = 0; i < edd->elements.num; i++) { - Eet_Data_Element *ede; - - ede = &(edd->elements.set[i]); - eet_group_codec[ede->group_type - 100].put(ed, edd, ede, ds, ((char *)data_in) + ede->offset); + Eet_Data_Element *ede; + + ede = &(edd->elements.set[i]); + eet_group_codec[ede->group_type - 100].put( + ed, + edd, + ede, + ds, + ((char *)data_in) + + ede->offset); } - chnk = eet_data_chunk_new(ds->data, ds->pos, edd->name, EET_T_UNKNOW, EET_G_UNKNOWN); + chnk = eet_data_chunk_new(ds->data, + ds->pos, + edd->name, + EET_T_UNKNOW, + EET_G_UNKNOWN); ds->data = NULL; ds->size = 0; eet_data_stream_free(ds); @@ -2988,10 +4873,154 @@ _eet_data_descriptor_encode(Eet_Dictionary *ed, return cdata; } +EAPI int +eet_data_node_write_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + Eet_Node *node, + int comp) +{ + Eet_Dictionary *ed; + void *data_enc; + int size; + int val; + + ed = eet_dictionary_get(ef); + + data_enc = _eet_data_dump_encode(EET_G_UNKNOWN, ed, node, &size); + if (!data_enc) + return 0; + + val = eet_write_cipher(ef, name, data_enc, size, comp, cipher_key); + free(data_enc); + return val; +} + +EAPI void * +eet_data_node_encode_cipher(Eet_Node *node, + const char *cipher_key, + int *size_ret) +{ + void *ret = NULL; + void *ciphered = NULL; + unsigned int ciphered_len = 0; + int size; + + ret = _eet_data_dump_encode(EET_G_UNKNOWN, NULL, node, &size); + if (cipher_key && ret) + { + if (eet_cipher(ret, size, cipher_key, + strlen(cipher_key), &ciphered, &ciphered_len)) + { + if (ciphered) + free(ciphered); + + if (size_ret) + *size_ret = 0; + + free(ret); + return NULL; + } + + free(ret); + size = (int)ciphered_len; + ret = ciphered; + } + + if (size_ret) + *size_ret = size; + + return ret; +} + +EAPI void * +eet_data_descriptor_encode_cipher(Eet_Data_Descriptor *edd, + const void *data_in, + const char *cipher_key, + int *size_ret) +{ + void *ret = NULL; + void *ciphered = NULL; + unsigned int ciphered_len = 0; + int size; + + EINA_SAFETY_ON_NULL_RETURN_VAL(edd, NULL); + + ret = _eet_data_descriptor_encode(NULL, edd, data_in, &size); + if (cipher_key && ret) + { + if (eet_cipher(ret, size, cipher_key, + strlen(cipher_key), &ciphered, &ciphered_len)) + { + if (ciphered) + free(ciphered); + + if (size_ret) + *size_ret = 0; + + free(ret); + return NULL; + } + + free(ret); + size = ciphered_len; + ret = ciphered; + } + + if (size_ret) + *size_ret = size; + + return ret; +} + EAPI void * eet_data_descriptor_encode(Eet_Data_Descriptor *edd, - const void *data_in, - int *size_ret) + const void *data_in, + int *size_ret) +{ + return eet_data_descriptor_encode_cipher(edd, data_in, NULL, size_ret); +} + +EAPI void * +eet_data_xattr_cipher_get(const char *filename, + const char *attribute, + Eet_Data_Descriptor *edd, + const char *cipher_key) +{ + void *blob; + void *ret; + ssize_t size; + + EINA_SAFETY_ON_NULL_RETURN_VAL(edd, NULL); + + blob = eina_xattr_get(filename, attribute, &size); + if (!blob) return NULL; + + ret = eet_data_descriptor_decode_cipher(edd, blob, cipher_key, size); + free(blob); + + return ret; +} + +EAPI Eina_Bool +eet_data_xattr_cipher_set(const char *filename, + const char *attribute, + Eet_Data_Descriptor *edd, + const char *cipher_key, + const void *data, + Eina_Xattr_Flags flags) { - return _eet_data_descriptor_encode(NULL, edd, data_in, size_ret); + void *blob; + int size; + Eina_Bool ret; + + EINA_SAFETY_ON_NULL_RETURN_VAL(edd, EINA_FALSE); + + blob = eet_data_descriptor_encode_cipher(edd, data, cipher_key, &size); + if (!blob) return EINA_FALSE; + + ret = eina_xattr_set(filename, attribute, blob, size, flags); + free(blob); + + return ret; } diff --git a/src/lib/eet_dictionary.c b/src/lib/eet_dictionary.c index 666282b..aef8ad2 100644 --- a/src/lib/eet_dictionary.c +++ b/src/lib/eet_dictionary.c @@ -1,28 +1,27 @@ -/* - * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 - */ - #ifdef HAVE_CONFIG_H # include -#endif +#endif /* ifdef HAVE_CONFIG_H */ #include #include #include +#include + #include "Eet.h" #include "Eet_private.h" Eet_Dictionary * eet_dictionary_add(void) { - Eet_Dictionary *new; + Eet_Dictionary *new; - new = calloc(1, sizeof (Eet_Dictionary)); + new = eet_dictionary_calloc(1); if (!new) return NULL; memset(new->hash, -1, sizeof (int) * 256); + eina_lock_new(&new->mutex); return new; } @@ -30,111 +29,118 @@ eet_dictionary_add(void) void eet_dictionary_free(Eet_Dictionary *ed) { - if (ed) - { - int i; + int i; - for (i = 0; i < ed->count; ++i) - if (ed->all[i].str) - free(ed->all[i].str); - if (ed->all) free(ed->all); - free(ed); - } + if (!ed) return; + + eina_lock_free(&ed->mutex); + + for (i = 0; i < ed->count; ++i) + if (ed->all[i].allocated) + eina_stringshare_del(ed->all[i].str); + + if (ed->all) + free(ed->all); + + if (ed->converts) eina_hash_free(ed->converts); + + eet_dictionary_mp_free(ed); } static int -_eet_dictionary_lookup(Eet_Dictionary *ed, const char *string, int hash) +_eet_dictionary_lookup(Eet_Dictionary *ed, + const char *string, + int len, + int hash) { - int prev = -1; - int current; + Eina_Bool found = EINA_FALSE; + int prev = -1; + int current; current = ed->hash[hash]; while (current != -1) { - if (ed->all[current].str) + if (ed->all[current].len == len) { - if (strcmp(ed->all[current].str, string) >= 0) - break ; - } - if (ed->all[current].mmap) - { - if (strcmp(ed->all[current].mmap, string) >= 0) - break ; + if (ed->all[current].str && + ((ed->all[current].str == string) || + (!strcmp(ed->all[current].str, string)))) + { + found = EINA_TRUE; + break; + } } prev = current; current = ed->all[current].next; } - if (current == -1) + if ((current == -1) && found) return prev; return current; } int -eet_dictionary_string_add(Eet_Dictionary *ed, const char *string) +eet_dictionary_string_add(Eet_Dictionary *ed, + const char *string) { - Eet_String *current; - char *str; - int hash; - int index; - int len; + Eet_String *current; + const char *str; + int hash; + int idx; + int len; + int cnt; if (!ed) return -1; hash = _eet_hash_gen(string, 8); + len = strlen(string) + 1; + + eina_lock_take(&ed->mutex); - index = _eet_dictionary_lookup(ed, string, hash); + idx = _eet_dictionary_lookup(ed, string, len, hash); - if (index != -1) + if (idx != -1) { - if (ed->all[index].str) - { - if (strcmp(ed->all[index].str, string) == 0) - return index; - } - if (ed->all[index].mmap) - { - if (strcmp(ed->all[index].mmap, string) == 0) - return index; - } + if (ed->all[idx].str && + ((ed->all[idx].str == string) || + (!strcmp(ed->all[idx].str, string)))) + { + eina_lock_release(&ed->mutex); + return idx; + } } if (ed->total == ed->count) { - Eet_String *new; - int total; + Eet_String *new; + int total; total = ed->total + 8; - new = realloc(ed->all, sizeof (Eet_String) * total); - if (new == NULL) - return -1; + new = realloc(ed->all, total * sizeof(Eet_String)); + if (!new) goto on_error; ed->all = new; ed->total = total; } - len = strlen(string) + 1; - str = strdup(string); - if (str == NULL) - return -1; + str = eina_stringshare_add(string); + if (!str) goto on_error; current = ed->all + ed->count; - current->flags.converted = 0; - current->flags.is_float = 0; + current->allocated = EINA_TRUE; current->hash = hash; current->str = str; current->len = len; - current->mmap = NULL; - if (index == -1) + if (idx == -1) { current->next = ed->hash[hash]; current->prev = -1; @@ -142,194 +148,367 @@ eet_dictionary_string_add(Eet_Dictionary *ed, const char *string) } else { - current->next = index; - current->prev = ed->all[index].prev; + current->next = idx; + current->prev = ed->all[idx].prev; if (current->next != -1) ed->all[current->next].prev = ed->count; + if (current->prev != -1) ed->all[current->prev].next = ed->count; else ed->hash[hash] = ed->count; } - return ed->count++; + cnt = ed->count++; + eina_lock_release(&ed->mutex); + return cnt; + + on_error: + eina_lock_release(&ed->mutex); + return -1; } int -eet_dictionary_string_get_size(const Eet_Dictionary *ed, int index) +eet_dictionary_string_get_size(const Eet_Dictionary *ed, + int idx) { - if (!ed) return 0; - if (index < 0) return 0; - if (index < ed->count) - return ed->all[index].len; - return 0; + int length = 0; + + if (!ed) goto done; + + if (idx < 0) goto done; + + eina_lock_take((Eina_Lock*) &ed->mutex); + + if (idx < ed->count) + length = ed->all[idx].len; + + eina_lock_release((Eina_Lock*) &ed->mutex); + + done: + return length; +} + +EAPI int +eet_dictionary_count(const Eet_Dictionary *ed) +{ + return ed->count; } int -eet_dictionary_string_get_hash(const Eet_Dictionary *ed, int index) +eet_dictionary_string_get_hash(const Eet_Dictionary *ed, + int idx) { - if (!ed) return -1; - if (index < 0) return -1; - if (index < ed->count) - return ed->all[index].hash; - return -1; + int hash = -1; + + if (!ed) goto done; + + if (idx < 0) goto done; + + eina_lock_take((Eina_Lock*) &ed->mutex); + + if (idx < ed->count) + hash = ed->all[idx].hash; + + eina_lock_release((Eina_Lock*) &ed->mutex); + + done: + return hash; } const char * -eet_dictionary_string_get_char(const Eet_Dictionary *ed, int index) +eet_dictionary_string_get_char(const Eet_Dictionary *ed, + int idx) { - if (!ed) return NULL; - if (index < 0) return NULL; - if (index < ed->count) + const char *s = NULL; + + if (!ed) goto done; + + if (idx < 0) goto done; + + eina_lock_take((Eina_Lock*) &ed->mutex); + + if (idx < ed->count) { #ifdef _WIN32 - /* Windows file system could change the mmaped file when replacing a file. So we need to copy all string in memory to avoid bugs. */ - if (ed->all[index].str == NULL) - { - ed->all[index].str = strdup(ed->all[index].mmap); - ed->all[index].mmap = NULL; - } -#else - if (ed->all[index].mmap) - return ed->all[index].mmap; -#endif - return ed->all[index].str; + /* Windows file system could change the mmaped file when replacing a file. So we need to copy all string in memory to avoid bugs. */ + if (!ed->all[idx].allocated) + { + ed->all[idx].str = eina_stringshare_add(ed->all[idx].str); + ed->all[idx].allocated = EINA_TRUE; + } +#endif /* ifdef _WIN32 */ + s = ed->all[idx].str; } - return NULL; + + eina_lock_release((Eina_Lock*) &ed->mutex); + + done: + return s; } -static inline int -_eet_dictionary_string_get_me_cache(const char *s, int len, int *mantisse, int *exponent) +static inline Eina_Bool +_eet_dictionary_string_get_me_cache(const char *s, + int len, + int *mantisse, + int *exponent) { if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p')) { *mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0'); *exponent = (s[5] - '0'); - return -1; + return EINA_TRUE; } - return 0; + + return EINA_FALSE; } -static inline int -_eet_dictionary_string_get_float_cache(const char *s, int len, float *result) +static inline Eina_Bool +_eet_dictionary_string_get_float_cache(const char *s, + int len, + float *result) { - int mantisse; - int exponent; + int mantisse; + int exponent; if (_eet_dictionary_string_get_me_cache(s, len, &mantisse, &exponent)) { - if (s[4] == '+') *result = (float) (mantisse << exponent); - else *result = (float) mantisse / (float) (1 << exponent); + if (s[4] == '+') + *result = (float)(mantisse << exponent); + else + *result = (float)mantisse / (float)(1 << exponent); - return -1; + return EINA_TRUE; } - return 0; + + return EINA_FALSE; } -static inline int -_eet_dictionary_string_get_double_cache(const char *s, int len, double *result) +static inline Eina_Bool +_eet_dictionary_string_get_double_cache(const char *s, + int len, + double *result) { - int mantisse; - int exponent; + int mantisse; + int exponent; if (_eet_dictionary_string_get_me_cache(s, len, &mantisse, &exponent)) { - if (s[4] == '+') *result = (double) (mantisse << exponent); - else *result = (double) mantisse / (float) (1 << exponent); + if (s[4] == '+') + *result = (double)(mantisse << exponent); + else + *result = (double)mantisse / (float)(1 << exponent); - return -1; + return EINA_TRUE; } - return 0; + + return EINA_FALSE; } -int -eet_dictionary_string_get_float(const Eet_Dictionary *ed, int index, float *result) +static inline Eina_Bool +_eet_dictionary_test(const Eet_Dictionary *ed, + int idx, + void *result) { - if (!result) return 0; - if (!ed) return 0; - if (index < 0) return 0; - if (index < ed->count) + Eina_Bool limit = EINA_FALSE; + + if (!result) goto done; + + if (!ed) goto done; + + if (idx < 0) goto done; + + eina_lock_take((Eina_Lock*) &ed->mutex); + + if (!(idx < ed->count)) goto unlock_done; + + limit = EINA_TRUE; + + unlock_done: + eina_lock_release((Eina_Lock*) &ed->mutex); + + done: + return limit; +} + +static Eet_Convert * +eet_dictionary_convert_get(const Eet_Dictionary *ed, + int idx, + const char **str) +{ + Eet_Convert *result; + + eina_lock_take((Eina_Lock*) &ed->mutex); + + *str = ed->all[idx].str; + + if (!ed->converts) { - if (!(ed->all[index].flags.converted - && ed->all[index].flags.is_float)) - { - const char *str; + ((Eet_Dictionary *)ed)->converts = eina_hash_int32_new(free); - str = ed->all[index].str ? ed->all[index].str : ed->all[index].mmap; + goto add_convert; + } - if (!_eet_dictionary_string_get_float_cache(str, ed->all[index].len, &ed->all[index].convert.f)) - { - long long mantisse = 0; - long exponent = 0; + result = eina_hash_find(ed->converts, &idx); + if (result) goto done; - if (!_eet_string_to_double_convert(str, &mantisse, &exponent)) - return 0; + add_convert: + result = calloc(1, sizeof (Eet_Convert)); + + eina_hash_add(ed->converts, &idx, result); + + done: + eina_lock_release((Eina_Lock*) &ed->mutex); + + return result; +} + +Eina_Bool +eet_dictionary_string_get_float(const Eet_Dictionary *ed, + int idx, + float *result) +{ + Eet_Convert *convert; + const char *str; + + if (!_eet_dictionary_test(ed, idx, result)) + return EINA_FALSE; + + convert = eet_dictionary_convert_get(ed, idx, &str); + if (!convert) return EINA_FALSE; + + if (!(convert->type & EET_D_FLOAT)) + { + eina_lock_take((Eina_Lock*) &ed->mutex); + if (!_eet_dictionary_string_get_float_cache(str, ed->all[idx].len, + &convert->f)) + { + long long mantisse = 0; + long exponent = 0; - ed->all[index].convert.f = ldexpf((float) mantisse, exponent); + if (eina_convert_atod(str, ed->all[idx].len, &mantisse, + &exponent) == EINA_FALSE) + { + eina_lock_release((Eina_Lock*) &ed->mutex); + return EINA_FALSE; } - ed->all[index].flags.is_float = 1; + convert->f = ldexpf((float)mantisse, exponent); } + eina_lock_release((Eina_Lock*) &ed->mutex); - *result = ed->all[index].convert.f; - return -1; + convert->type |= EET_D_FLOAT; } - return 0; + + *result = convert->f; + return EINA_TRUE; } -int -eet_dictionary_string_get_double(const Eet_Dictionary *ed, int index, double *result) +Eina_Bool +eet_dictionary_string_get_double(const Eet_Dictionary *ed, + int idx, + double *result) { - if (!result) return 0; - if (!ed) return 0; - if (index < 0) return 0; - if (index < ed->count) + Eet_Convert *convert; + const char *str; + + if (!_eet_dictionary_test(ed, idx, result)) + return EINA_FALSE; + + convert = eet_dictionary_convert_get(ed, idx, &str); + if (!convert) return EINA_FALSE; + + if (!(convert->type & EET_D_DOUBLE)) { - if (!(ed->all[index].flags.converted - && !ed->all[index].flags.is_float)) - { - const char *str; + eina_lock_take((Eina_Lock*) &ed->mutex); - str = ed->all[index].str ? ed->all[index].str : ed->all[index].mmap; + if (!_eet_dictionary_string_get_double_cache(str, ed->all[idx].len, + &convert->d)) + { + long long mantisse = 0; + long exponent = 0; - if (!_eet_dictionary_string_get_double_cache(str, ed->all[index].len, &ed->all[index].convert.d)) + if (eina_convert_atod(str, ed->all[idx].len, &mantisse, + &exponent) == EINA_FALSE) { - long long mantisse = 0; - long exponent = 0; + eina_lock_release((Eina_Lock*) &ed->mutex); + return EINA_FALSE; + } - if (!_eet_string_to_double_convert(str, &mantisse, &exponent)) - return 0; + convert->d = ldexp((double)mantisse, exponent); + } + eina_lock_release((Eina_Lock*) &ed->mutex); - ed->all[index].convert.d = ldexp((double) mantisse, exponent); - } + convert->type |= EET_D_DOUBLE; + } - ed->all[index].flags.is_float = 0; + *result = convert->d; + return EINA_TRUE; +} + +Eina_Bool +eet_dictionary_string_get_fp(const Eet_Dictionary *ed, + int idx, + Eina_F32p32 *result) +{ + Eet_Convert *convert; + const char *str; + + if (!_eet_dictionary_test(ed, idx, result)) + return EINA_FALSE; + + convert = eet_dictionary_convert_get(ed, idx, &str); + if (!convert) return EINA_FALSE; + + if (!(convert->type & EET_D_FIXED_POINT)) + { + Eina_F32p32 fp; + + eina_lock_take((Eina_Lock*) &ed->mutex); + if (!eina_convert_atofp(str, ed->all[idx].len, &fp)) + { + eina_lock_release((Eina_Lock*) &ed->mutex); + return EINA_FALSE; } + eina_lock_release((Eina_Lock*) &ed->mutex); - *result = ed->all[index].convert.d; - return -1; + convert->fp = fp; + convert->type |= EET_D_FIXED_POINT; } - return 0; + + *result = convert->fp; + return EINA_TRUE; } EAPI int -eet_dictionary_string_check(Eet_Dictionary *ed, const char *string) +eet_dictionary_string_check(Eet_Dictionary *ed, + const char *string) { - int i; + int res = 0; + int i; - if (ed == NULL - || string == NULL) + if ((!ed) || (!string)) return 0; - if (ed->start <= string - && string < ed->end) - return 1; + eina_lock_take(&ed->mutex); - for (i = 0; i < ed->count; ++i) - if (ed->all[i].str == string) - return 1; + if ((ed->start <= string) && (string < ed->end)) + res = 1; - return 0; + if (!res) + { + for (i = 0; i < ed->count; ++i) + if ((ed->all[i].allocated) && ed->all[i].str == string) + { + res = 1; + break; + } + } + + eina_lock_release(&ed->mutex); + + return res; } + diff --git a/src/lib/eet_image.c b/src/lib/eet_image.c index baeff52..7116a3c 100644 --- a/src/lib/eet_image.c +++ b/src/lib/eet_image.c @@ -1,10 +1,6 @@ -/* - * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 - */ - #ifdef HAVE_CONFIG_H # include -#endif +#endif /* ifdef HAVE_CONFIG_H */ #ifdef HAVE_ALLOCA_H # include @@ -15,81 +11,322 @@ #elif defined _MSC_VER # include # define alloca _alloca -#else +#else /* ifdef HAVE_ALLOCA_H */ # include # ifdef __cplusplus extern "C" -# endif -void *alloca (size_t); -#endif +# endif /* ifdef __cplusplus */ +void *alloca(size_t); +#endif /* ifdef HAVE_ALLOCA_H */ #ifdef HAVE_NETINET_IN_H +# ifdef __OpenBSD__ +# include +# endif /* ifdef __OpenBSD__ */ # include -#endif +#endif /* ifdef HAVE_NETINET_IN_H */ + +#ifdef _WIN32 +# include +# define HAVE_BOOLEAN +#endif /* ifdef _WIN32 */ #include #include +#include #include #include -#include #include "Eet.h" #include "Eet_private.h" +#include "lz4.h" +#include "lz4hc.h" + /*---*/ -typedef struct _JPEG_error_mgr *emptr; +typedef struct _JPEG_error_mgr *emptr; /*---*/ struct _JPEG_error_mgr { - struct jpeg_error_mgr pub; - jmp_buf setjmp_buffer; + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; +}; + +struct jpeg_membuf_src +{ + struct jpeg_source_mgr pub; + + const unsigned char *buf; + size_t len; + struct jpeg_membuf_src *self; }; +static void +_eet_jpeg_membuf_src_init(j_decompress_ptr cinfo) +{ + /* FIXME: Use attribute unused */ + (void)cinfo; +} + +static boolean +_eet_jpeg_membuf_src_fill(j_decompress_ptr cinfo) +{ + static const JOCTET jpeg_eoi[2] = { 0xFF, JPEG_EOI }; + struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src; + + src->pub.bytes_in_buffer = sizeof(jpeg_eoi); + src->pub.next_input_byte = jpeg_eoi; + + return TRUE; +} + +static void +_eet_jpeg_membuf_src_skip(j_decompress_ptr cinfo, + long num_bytes) +{ + struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src; + + src->pub.bytes_in_buffer -= num_bytes; + src->pub.next_input_byte += num_bytes; +} + +static void +_eet_jpeg_membuf_src_term(j_decompress_ptr cinfo) +{ + struct jpeg_membuf_src *src = ((struct jpeg_membuf_src *)cinfo->src)->self; + + free(src); + cinfo->src = NULL; +} + +static int +eet_jpeg_membuf_src(j_decompress_ptr cinfo, + const void *buf, + size_t len) +{ + struct jpeg_membuf_src *src; + + src = calloc(1, sizeof(*src)); + if (!src) + return -1; + + src->self = src; + + cinfo->src = &src->pub; + src->buf = buf; + src->len = len; + src->pub.init_source = _eet_jpeg_membuf_src_init; + src->pub.fill_input_buffer = _eet_jpeg_membuf_src_fill; + src->pub.skip_input_data = _eet_jpeg_membuf_src_skip; + src->pub.resync_to_restart = jpeg_resync_to_restart; + src->pub.term_source = _eet_jpeg_membuf_src_term; + src->pub.bytes_in_buffer = src->len; + src->pub.next_input_byte = src->buf; + + return 0; +} + +struct jpeg_membuf_dst +{ + struct jpeg_destination_mgr pub; + + void **dst_buf; + size_t *dst_len; + + unsigned char *buf; + size_t len; + int failed; + struct jpeg_membuf_dst *self; +}; + +static void +_eet_jpeg_membuf_dst_init(j_compress_ptr cinfo) +{ + /* FIXME: Use eina attribute */ + (void)cinfo; +} + +static boolean +_eet_jpeg_membuf_dst_flush(j_compress_ptr cinfo) +{ + struct jpeg_membuf_dst *dst = (struct jpeg_membuf_dst *)cinfo->dest; + unsigned char *buf; + + if (dst->len >= 0x40000000 || + !(buf = realloc(dst->buf, dst->len * 2))) + { + dst->failed = 1; + dst->pub.next_output_byte = dst->buf; + dst->pub.free_in_buffer = dst->len; + return TRUE; + } + + dst->pub.next_output_byte = + buf + ((unsigned char *)dst->pub.next_output_byte - dst->buf); + dst->buf = buf; + dst->pub.free_in_buffer += dst->len; + dst->len *= 2; + + return FALSE; +} + +static void +_eet_jpeg_membuf_dst_term(j_compress_ptr cinfo) +{ + struct jpeg_membuf_dst *dst = ((struct jpeg_membuf_dst *)cinfo->dest)->self; + + if (dst->failed) + { + *dst->dst_buf = NULL; + *dst->dst_len = 0; + free(dst->buf); + } + else + { + *dst->dst_buf = dst->buf; + *dst->dst_len = (unsigned char *)dst->pub.next_output_byte - dst->buf; + } + + free(dst); + cinfo->dest = NULL; +} + +static int +eet_jpeg_membuf_dst(j_compress_ptr cinfo, + void **buf, + size_t *len) +{ + struct jpeg_membuf_dst *dst; + + dst = calloc(1, sizeof(*dst)); + if (!dst) + return -1; + + dst->buf = malloc(32768); + if (!dst->buf) + { + free(dst); + return -1; + } + + dst->self = dst; + dst->len = 32768; + + cinfo->dest = &dst->pub; + dst->pub.init_destination = _eet_jpeg_membuf_dst_init; + dst->pub.empty_output_buffer = _eet_jpeg_membuf_dst_flush; + dst->pub.term_destination = _eet_jpeg_membuf_dst_term; + dst->pub.free_in_buffer = dst->len; + dst->pub.next_output_byte = dst->buf; + dst->dst_buf = buf; + dst->dst_len = len; + dst->failed = 0; + + return 0; +} + /*---*/ static void _JPEGFatalErrorHandler(j_common_ptr cinfo); static void _JPEGErrorHandler(j_common_ptr cinfo); -static void _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level); +static void _JPEGErrorHandler2(j_common_ptr cinfo, + int msg_level); -static int eet_data_image_jpeg_header_decode(const void *data, int size, unsigned int *w, unsigned int *h); -static int eet_data_image_jpeg_rgb_decode(const void *data, int size, unsigned int src_x, unsigned int src_y, unsigned int *d, unsigned int w, unsigned int h, unsigned int row_stride); -static void *eet_data_image_jpeg_alpha_decode(const void *data, int size, unsigned int src_x, unsigned int src_y, unsigned int *d, unsigned int w, unsigned int h, unsigned int row_stride); -static void *eet_data_image_lossless_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha); -static void *eet_data_image_lossless_compressed_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha, int compression); -static void *eet_data_image_jpeg_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha, int quality); -static void *eet_data_image_jpeg_alpha_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha, int quality); +static int +eet_data_image_jpeg_header_decode(const void *data, + int size, + unsigned int *w, + unsigned int *h); +static int +eet_data_image_jpeg_rgb_decode(const void *data, + int size, + unsigned int src_x, + unsigned int src_y, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride); +static int +eet_data_image_jpeg_alpha_decode(const void *data, + int size, + unsigned int src_x, + unsigned int src_y, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride); +static void * +eet_data_image_lossless_convert(int *size, + const void *data, + unsigned int w, + unsigned int h, + int alpha); +static void * +eet_data_image_lossless_compressed_convert(int *size, + const void *data, + unsigned int w, + unsigned int h, + int alpha, + int compression); +static void * +eet_data_image_jpeg_convert(int *size, + const void *data, + unsigned int w, + unsigned int h, + int alpha, + int quality); +static void * +eet_data_image_jpeg_alpha_convert(int *size, + const void *data, + unsigned int w, + unsigned int h, + int alpha, + int quality); /*---*/ -static int words_bigendian = -1; +static int _eet_image_words_bigendian = -1; /*---*/ -#define SWAP64(x) (x) = \ - ((((unsigned long long)(x) & 0x00000000000000ffULL ) << 56) |\ - (((unsigned long long)(x) & 0x000000000000ff00ULL ) << 40) |\ - (((unsigned long long)(x) & 0x0000000000ff0000ULL ) << 24) |\ - (((unsigned long long)(x) & 0x00000000ff000000ULL ) << 8) |\ - (((unsigned long long)(x) & 0x000000ff00000000ULL ) >> 8) |\ - (((unsigned long long)(x) & 0x0000ff0000000000ULL ) >> 24) |\ - (((unsigned long long)(x) & 0x00ff000000000000ULL ) >> 40) |\ - (((unsigned long long)(x) & 0xff00000000000000ULL ) >> 56)) -#define SWAP32(x) (x) = \ - ((((int)(x) & 0x000000ff ) << 24) |\ - (((int)(x) & 0x0000ff00 ) << 8) |\ - (((int)(x) & 0x00ff0000 ) >> 8) |\ - (((int)(x) & 0xff000000 ) >> 24)) -#define SWAP16(x) (x) = \ - ((((short)(x) & 0x00ff ) << 8) |\ - (((short)(x) & 0xff00 ) >> 8)) +#define SWAP64(x) (x) = \ + ((((unsigned long long)(x) & 0x00000000000000ffULL) << 56) | \ + (((unsigned long long)(x) & 0x000000000000ff00ULL) << 40) | \ + (((unsigned long long)(x) & 0x0000000000ff0000ULL) << 24) | \ + (((unsigned long long)(x) & 0x00000000ff000000ULL) << 8) | \ + (((unsigned long long)(x) & 0x000000ff00000000ULL) >> 8) | \ + (((unsigned long long)(x) & 0x0000ff0000000000ULL) >> 24) | \ + (((unsigned long long)(x) & 0x00ff000000000000ULL) >> 40) | \ + (((unsigned long long)(x) & 0xff00000000000000ULL) >> 56)) +#define SWAP32(x) (x) = \ + ((((int)(x) & 0x000000ff) << 24) | \ + (((int)(x) & 0x0000ff00) << 8) | \ + (((int)(x) & 0x00ff0000) >> 8) | \ + (((int)(x) & 0xff000000) >> 24)) +#define SWAP16(x) (x) = \ + ((((short)(x) & 0x00ff) << 8) | \ + (((short)(x) & 0xff00) >> 8)) + +#ifdef CONV8 +# undef CONV8 +#endif /* ifdef CONV8 */ +#ifdef CONV16 +# undef CONV16 +#endif /* ifdef CONV16 */ +#ifdef CONV32 +# undef CONV32 +#endif /* ifdef CONV32 */ +#ifdef CONV64 +# undef CONV64 +#endif /* ifdef CONV64 */ #define CONV8(x) -#define CONV16(x) {if (words_bigendian) SWAP16(x);} -#define CONV32(x) {if (words_bigendian) SWAP32(x);} -#define CONV64(x) {if (words_bigendian) SWAP64(x);} +#define CONV16(x) {if (_eet_image_words_bigendian) {SWAP16(x); }} +#define CONV32(x) {if (_eet_image_words_bigendian) {SWAP32(x); }} +#define CONV64(x) {if (_eet_image_words_bigendian) {SWAP64(x); }} /*---*/ @@ -98,56 +335,61 @@ _JPEGFatalErrorHandler(j_common_ptr cinfo) { emptr errmgr; - errmgr = (emptr) cinfo->err; + errmgr = (emptr)cinfo->err; /* cinfo->err->output_message(cinfo);*/ longjmp(errmgr->setjmp_buffer, 1); return; } static void -_JPEGErrorHandler(j_common_ptr cinfo) +_JPEGErrorHandler(j_common_ptr cinfo __UNUSED__) { - emptr errmgr; + /* emptr errmgr; */ - errmgr = (emptr) cinfo->err; - /* cinfo->err->output_message(cinfo);*/ - /* longjmp(errmgr->setjmp_buffer, 1);*/ - return; + /* errmgr = (emptr) cinfo->err; */ + /* cinfo->err->output_message(cinfo);*/ + /* longjmp(errmgr->setjmp_buffer, 1);*/ + return; } static void -_JPEGErrorHandler2(j_common_ptr cinfo, int msg_level) +_JPEGErrorHandler2(j_common_ptr cinfo __UNUSED__, + int msg_level __UNUSED__) { - emptr errmgr; + /* emptr errmgr; */ - errmgr = (emptr) cinfo->err; - /* cinfo->err->output_message(cinfo);*/ - /* longjmp(errmgr->setjmp_buffer, 1);*/ - return; - msg_level = 0; + /* errmgr = (emptr) cinfo->err; */ + /* cinfo->err->output_message(cinfo);*/ + /* longjmp(errmgr->setjmp_buffer, 1);*/ + return; } static int -eet_data_image_jpeg_header_decode(const void *data, int size, unsigned int *w, unsigned int *h) +eet_data_image_jpeg_header_decode(const void *data, + int size, + unsigned int *w, + unsigned int *h) { struct jpeg_decompress_struct cinfo; struct _JPEG_error_mgr jerr; - FILE *f; - f = _eet_memfile_read_open(data, (size_t)size); - if (!f) return 0; + memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct)); + cinfo.err = jpeg_std_error(&(jerr.pub)); jerr.pub.error_exit = _JPEGFatalErrorHandler; jerr.pub.emit_message = _JPEGErrorHandler2; jerr.pub.output_message = _JPEGErrorHandler; if (setjmp(jerr.setjmp_buffer)) + return 0; + + jpeg_create_decompress(&cinfo); + + if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size)) { - jpeg_destroy_decompress(&cinfo); - _eet_memfile_read_close(f); - return 0; + jpeg_destroy_decompress(&cinfo); + return 0; } - jpeg_create_decompress(&cinfo); - jpeg_stdio_src(&cinfo, f); + jpeg_read_header(&cinfo, TRUE); cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; @@ -156,51 +398,59 @@ eet_data_image_jpeg_header_decode(const void *data, int size, unsigned int *w, u /* head decoding */ *w = cinfo.output_width; *h = cinfo.output_height; - if ((*w < 1) || (*h < 1) || (*w > 8192) || (*h > 8192)) - { - jpeg_destroy_decompress(&cinfo); - _eet_memfile_read_close(f); - return 0; - } - /* end head decoding */ + + free(cinfo.src); + cinfo.src = NULL; + jpeg_destroy_decompress(&cinfo); - _eet_memfile_read_close(f); + + if ((*w < 1) || (*h < 1) || (*w > 8192) || (*h > 8192)) + return 0; + return 1; } static int -eet_data_image_jpeg_rgb_decode(const void *data, int size, unsigned int src_x, unsigned int src_y, - unsigned int *d, unsigned int w, unsigned int h, unsigned int row_stride) +eet_data_image_jpeg_rgb_decode(const void *data, + int size, + unsigned int src_x, + unsigned int src_y, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride) { struct jpeg_decompress_struct cinfo; struct _JPEG_error_mgr jerr; unsigned char *ptr, *line[16], *tdata = NULL; unsigned int *ptr2, *tmp; unsigned int iw, ih; - int x, y, l, scans; - int i, count, prevy; - FILE *f; + unsigned int x, y, l, scans; + unsigned int i; /* FIXME: handle src_x, src_y and row_stride correctly */ - if (!d) return 0; + if (!d) + return 0; + + memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct)); - f = _eet_memfile_read_open(data, (size_t)size); - if (!f) return 0; cinfo.err = jpeg_std_error(&(jerr.pub)); jerr.pub.error_exit = _JPEGFatalErrorHandler; jerr.pub.emit_message = _JPEGErrorHandler2; jerr.pub.output_message = _JPEGErrorHandler; if (setjmp(jerr.setjmp_buffer)) + return 0; + + jpeg_create_decompress(&cinfo); + + if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size)) { - if (tdata) free(tdata); - jpeg_destroy_decompress(&cinfo); - _eet_memfile_read_close(f); - return 0; + jpeg_destroy_decompress(&cinfo); + return 0; } - jpeg_create_decompress(&cinfo); - jpeg_stdio_src(&cinfo, f); + jpeg_read_header(&cinfo, TRUE); - cinfo.dct_method = JDCT_FASTEST; + cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss) cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; jpeg_start_decompress(&cinfo); @@ -210,140 +460,149 @@ eet_data_image_jpeg_rgb_decode(const void *data, int size, unsigned int src_x, u ih = cinfo.output_height; if ((iw != w) || (ih != h)) { - jpeg_destroy_decompress(&cinfo); - _eet_memfile_read_close(f); - return 0; + free(cinfo.src); + cinfo.src = NULL; + + jpeg_destroy_decompress(&cinfo); + return 0; } + /* end head decoding */ /* data decoding */ if (cinfo.rec_outbuf_height > 16) { - jpeg_destroy_decompress(&cinfo); - _eet_memfile_read_close(f); - return 0; + free(cinfo.src); + cinfo.src = NULL; + + jpeg_destroy_decompress(&cinfo); + return 0; } + tdata = alloca((iw) * 16 * 3); ptr2 = d; - count = 0; - prevy = 0; if (cinfo.output_components == 3) { - for (i = 0; i < cinfo.rec_outbuf_height; i++) - line[i] = tdata + (i * (iw) * 3); - for (l = 0; l < ih; l += cinfo.rec_outbuf_height) - { - jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); - scans = cinfo.rec_outbuf_height; - if ((ih - l) < scans) scans = ih - l; - ptr = tdata; - - if (l + scans >= src_y && l < src_y + h) - { - y = src_y - l; - if (y < 0) y = 0; - for (ptr += 3 * iw * y; y < scans && (y + l) < (src_y + h); y++) - { - tmp = ptr2; - ptr += 3 * src_x; - for (x = 0; x < w; x++) - { - *ptr2 = - (0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]); - ptr += 3; - ptr2++; - } - ptr += 3 * (iw - w); - ptr2 = tmp + row_stride / 4; - } - } - else - { - ptr += 3 * iw * scans; - } - } + for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++) + line[i] = tdata + (i * (iw) * 3); + for (l = 0; l < ih; l += cinfo.rec_outbuf_height) + { + jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); + scans = cinfo.rec_outbuf_height; + if ((ih - l) < scans) + scans = ih - l; + + ptr = tdata; + + if (l + scans >= src_y && l < src_y + h) + { + y = src_y - l; + if (src_y < l) + y = 0; + + for (ptr += 3 * iw * y; y < scans && (y + l) < (src_y + h); + y++) + { + tmp = ptr2; + ptr += 3 * src_x; + for (x = 0; x < w; x++) + { + *ptr2 = + (0xff000000) | + ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]); + ptr += 3; + ptr2++; + } + ptr += 3 * (iw - w); + ptr2 = tmp + row_stride / 4; + } + } + } } else if (cinfo.output_components == 1) { - for (i = 0; i < cinfo.rec_outbuf_height; i++) - line[i] = tdata + (i * (iw)); - for (l = 0; l < (ih); l += cinfo.rec_outbuf_height) - { - jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); - scans = cinfo.rec_outbuf_height; - if (((ih) - l) < scans) scans = (ih) - l; - ptr = tdata; - - if (l >= src_y && l < src_y + h) - { - y = src_y - l; - if (y < 0) y = 0; - for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++) - { - tmp = ptr2; - ptr += src_x; - for (x = 0; x < w; x++) - { - *ptr2 = - (0xff000000) | ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]); - ptr++; - ptr2++; - } - ptr += iw - w; - ptr2 = tmp + row_stride / 4; - } - } - else - { - ptr += iw * scans; - } - } + for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++) + line[i] = tdata + (i * (iw)); + for (l = 0; l < (ih); l += cinfo.rec_outbuf_height) + { + jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); + scans = cinfo.rec_outbuf_height; + if (((ih) - l) < scans) + scans = (ih) - l; + + ptr = tdata; + + if (l >= src_y && l < src_y + h) + { + y = src_y - l; + if (src_y < l) + y = 0; + + for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++) + { + tmp = ptr2; + ptr += src_x; + for (x = 0; x < w; x++) + { + *ptr2 = + (0xff000000) | + ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]); + ptr++; + ptr2++; + } + ptr += iw - w; + ptr2 = tmp + row_stride / 4; + } + } + } } + /* end data decoding */ jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); - _eet_memfile_read_close(f); return 1; } -static void * -eet_data_image_jpeg_alpha_decode(const void *data, int size, unsigned int src_x, unsigned int src_y, - unsigned int *d, unsigned int w, unsigned int h, unsigned int row_stride) +static int +eet_data_image_jpeg_alpha_decode(const void *data, + int size, + unsigned int src_x, + unsigned int src_y, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride) { struct jpeg_decompress_struct cinfo; struct _JPEG_error_mgr jerr; unsigned char *ptr, *line[16], *tdata = NULL; unsigned int *ptr2, *tmp; - int x, y, l, scans; - int i, count, prevy, iw; - FILE *f; + unsigned int x, y, l, scans; + unsigned int i, iw; - f = _eet_memfile_read_open(data, (size_t)size); - if (!f) return NULL; + /* FIXME: handle src_x, src_y and row_stride correctly */ + if (!d) + return 0; - if (0) - { - char buf[1]; + memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct)); - while (fread(buf, 1, 1, f)); - _eet_memfile_read_close(f); - return d; - } cinfo.err = jpeg_std_error(&(jerr.pub)); jerr.pub.error_exit = _JPEGFatalErrorHandler; jerr.pub.emit_message = _JPEGErrorHandler2; jerr.pub.output_message = _JPEGErrorHandler; if (setjmp(jerr.setjmp_buffer)) + return 0; + + jpeg_create_decompress(&cinfo); + + if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size)) { - if (tdata) free(tdata); - jpeg_destroy_decompress(&cinfo); - _eet_memfile_read_close(f); - return NULL; + jpeg_destroy_decompress(&cinfo); + return 0; } - jpeg_create_decompress(&cinfo); - jpeg_stdio_src(&cinfo, f); + jpeg_read_header(&cinfo, TRUE); - cinfo.dct_method = JDCT_FASTEST; + cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss) cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; jpeg_start_decompress(&cinfo); @@ -353,418 +612,471 @@ eet_data_image_jpeg_alpha_decode(const void *data, int size, unsigned int src_x, if (w != cinfo.output_width || h != cinfo.output_height) { - jpeg_destroy_decompress(&cinfo); - _eet_memfile_read_close(f); - return NULL; + free(cinfo.src); + cinfo.src = NULL; + + jpeg_destroy_decompress(&cinfo); + return 0; } + /* end head decoding */ /* data decoding */ if (cinfo.rec_outbuf_height > 16) { - jpeg_destroy_decompress(&cinfo); - _eet_memfile_read_close(f); - return NULL; + free(cinfo.src); + cinfo.src = NULL; + + jpeg_destroy_decompress(&cinfo); + return 0; } + tdata = alloca(w * 16 * 3); ptr2 = d; - count = 0; - prevy = 0; + if (cinfo.output_components == 1) { - for (i = 0; i < cinfo.rec_outbuf_height; i++) - line[i] = tdata + (i * w); - for (l = 0; l < h; l += cinfo.rec_outbuf_height) - { - jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); - scans = cinfo.rec_outbuf_height; - if ((h - l) < scans) scans = h - l; - ptr = tdata; - - if (l >= src_y && l < src_y + h) - { - y = src_y - l; - if (y < 0) y = 0; - for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++) - { - tmp = ptr2; - ptr += src_x; - for (x = 0; x < w; x++) - { - *ptr2 = - ((*ptr2) & 0x00ffffff) | - ((ptr[0]) << 24); - ptr++; - ptr2++; - } - ptr += iw - w; - ptr2 = tmp + row_stride / 4; - } - } - else - { - ptr += iw * scans; - } - } + for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++) + line[i] = tdata + (i * w); + for (l = 0; l < h; l += cinfo.rec_outbuf_height) + { + jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); + scans = cinfo.rec_outbuf_height; + if ((h - l) < scans) + scans = h - l; + + ptr = tdata; + + if (l >= src_y && l < src_y + h) + { + y = src_y - l; + if (src_y < l) + y = 0; + + for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++) + { + tmp = ptr2; + ptr += src_x; + for (x = 0; x < w; x++) + { + *ptr2 = + ((*ptr2) & 0x00ffffff) | + ((ptr[0]) << 24); + ptr++; + ptr2++; + } + ptr += iw - w; + ptr2 = tmp + row_stride / 4; + } + } + } } + /* end data decoding */ jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); - _eet_memfile_read_close(f); - return d; + return 1; } static void * -eet_data_image_lossless_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha) +eet_data_image_lossless_convert(int *size, + const void *data, + unsigned int w, + unsigned int h, + int alpha) { - if (words_bigendian == -1) + if (_eet_image_words_bigendian == -1) { - unsigned long int v; + unsigned long int v; - v = htonl(0x12345678); - if (v == 0x12345678) words_bigendian = 1; - else words_bigendian = 0; + v = htonl(0x12345678); + if (v == 0x12345678) + _eet_image_words_bigendian = 1; + else + _eet_image_words_bigendian = 0; } - { - unsigned char *d; - int *header; - d = malloc((w * h * 4) + (8 * 4)); - if (!d) return NULL; + { + unsigned char *d; + int *header; - header = (int *)d; - memset(d, 0, 32); + d = malloc((w * h * 4) + (8 * 4)); + if (!d) + return NULL; - header[0] = 0xac1dfeed; - header[1] = w; - header[2] = h; - header[3] = alpha; + header = (int *)d; + memset(d, 0, 32); - memcpy(d + 32, data, w * h * 4); + header[0] = 0xac1dfeed; + header[1] = w; + header[2] = h; + header[3] = alpha; - if (words_bigendian) - { - unsigned int i; + memcpy(d + 32, data, w * h * 4); - for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]); - } - *size = ((w * h * 4) + (8 * 4)); - return d; - } + if (_eet_image_words_bigendian) + { + unsigned int i; + + for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]); + } + + *size = ((w * h * 4) + (8 * 4)); + return d; + } } static void * -eet_data_image_lossless_compressed_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha, int compression) +eet_data_image_lossless_compressed_convert(int *size, + const void *data, + unsigned int w, + unsigned int h, + int alpha, + int compression) { - if (words_bigendian == -1) + if (_eet_image_words_bigendian == -1) { - unsigned long int v; + unsigned long int v; - v = htonl(0x12345678); - if (v == 0x12345678) words_bigendian = 1; - else words_bigendian = 0; + v = htonl(0x12345678); + if (v == 0x12345678) + _eet_image_words_bigendian = 1; + else + _eet_image_words_bigendian = 0; } - { - unsigned char *d; - unsigned char *comp; - int *header; - int ret; - uLongf buflen; - - d = malloc((w * h * 4) + (8 * 4)); - if (!d) return NULL; - buflen = (((w * h * 101) / 100) + 3) * 4; - comp = malloc(buflen); - if (!comp) - { - free(d); - return NULL; - } - header = (int *)d; - memset(d, 0, 32); - - header[0] = 0xac1dfeed; - header[1] = w; - header[2] = h; - header[3] = alpha; - header[4] = compression; - memcpy(d + 32, data, w * h * 4); - - if (words_bigendian) - { - unsigned int i; - - for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]); - } - ret = compress2((Bytef *)comp, &buflen, - (Bytef *)(d + 32), - (uLong)(w * h * 4), - compression); - if (buflen > (w * h * 4)) - { - free(comp); - free(d); - *size = -1; - return NULL; - } - memcpy(d + 32, comp, buflen); - *size = (8 * 4) + buflen; - free(comp); - return d; - } + { + unsigned char *d, *comp; + int *header, ret, ok = 1; + uLongf buflen = 0; + + buflen = (((w * h * 101) / 100) + 3) * 4; + ret = LZ4_compressBound((w * h * 4)); + if ((ret > 0) && ((uLongf)ret > buflen)) buflen = ret; + + comp = malloc(buflen); + if (!comp) return NULL; + + switch (compression) + { + case EET_COMPRESSION_VERYFAST: + ret = LZ4_compressHC((const char *)data, (char *)comp, + (w * h * 4)); + if (ret <= 0) ok = 0; + buflen = ret; + break; + case EET_COMPRESSION_SUPERFAST: + ret = LZ4_compress((const char *)data, (char *)comp, + (w * h * 4)); + if (ret <= 0) ok = 0; + buflen = ret; + break; + default: /* zlib etc. */ + ret = compress2((Bytef *)comp, &buflen, (Bytef *)(data), + (uLong)(w * h * 4), compression); + if (ret != Z_OK) ok = 0; + break; + } + if ((!ok) || (buflen > (w * h * 4))) + { + free(comp); + *size = -1; + return NULL; + } + + d = malloc((8 * sizeof(int)) + buflen); + if (!d) + { + free(comp); + return NULL; + } + + header = (int *)d; + memset(d, 0, 8 * sizeof(int)); + header[0] = 0xac1dfeed; + header[1] = w; + header[2] = h; + header[3] = alpha; + header[4] = compression; + + if (_eet_image_words_bigendian) + { + unsigned int i; + + for (i = 0; i < 8; i++) SWAP32(header[i]); + } + + memcpy(d + (8 * sizeof(int)), comp, buflen); + *size = (8 * sizeof(int)) + buflen; + free(comp); + return d; + } } static void * -eet_data_image_jpeg_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha, int quality) +eet_data_image_jpeg_convert(int *size, + const void *data, + unsigned int w, + unsigned int h, + int alpha, + int quality) { + struct jpeg_compress_struct cinfo; + struct _JPEG_error_mgr jerr; const int *ptr; void *d = NULL; size_t sz = 0; - struct _JPEG_error_mgr jerr; JSAMPROW *jbuf; - struct jpeg_compress_struct cinfo; - FILE *f; unsigned char *buf; - (void) alpha; /* unused */ - - f =_eet_memfile_write_open(&d, &sz); - if (!f) return NULL; + (void)alpha; /* unused */ buf = alloca(3 * w); + memset(&cinfo, 0, sizeof (struct jpeg_compress_struct)); + cinfo.err = jpeg_std_error(&(jerr.pub)); jerr.pub.error_exit = _JPEGFatalErrorHandler; jerr.pub.emit_message = _JPEGErrorHandler2; jerr.pub.output_message = _JPEGErrorHandler; if (setjmp(jerr.setjmp_buffer)) + return NULL; + + jpeg_create_compress(&cinfo); + + if (eet_jpeg_membuf_dst(&cinfo, &d, &sz)) { - jpeg_destroy_compress(&cinfo); - _eet_memfile_write_close(f); - if (d) free(d); - return NULL; + jpeg_destroy_compress(&cinfo); + return NULL; } - jpeg_create_compress(&cinfo); - jpeg_stdio_dest(&cinfo, f); + cinfo.image_width = w; cinfo.image_height = h; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; + cinfo.optimize_coding = FALSE; + cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss) + if (quality < 60) cinfo.dct_method = JDCT_IFAST; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); + if (quality >= 90) { - cinfo.comp_info[0].h_samp_factor = 1; - cinfo.comp_info[0].v_samp_factor = 1; - cinfo.comp_info[1].h_samp_factor = 1; - cinfo.comp_info[1].v_samp_factor = 1; - cinfo.comp_info[2].h_samp_factor = 1; - cinfo.comp_info[2].v_samp_factor = 1; + cinfo.comp_info[0].h_samp_factor = 1; + cinfo.comp_info[0].v_samp_factor = 1; + cinfo.comp_info[1].h_samp_factor = 1; + cinfo.comp_info[1].v_samp_factor = 1; + cinfo.comp_info[2].h_samp_factor = 1; + cinfo.comp_info[2].v_samp_factor = 1; } + jpeg_start_compress(&cinfo, TRUE); - ptr = data; while (cinfo.next_scanline < cinfo.image_height) { - unsigned int i, j; - - /* convert scaline from ARGB to RGB packed */ - for (j = 0, i = 0; i < w; i++) - { - buf[j++] = ((*ptr) >> 16) & 0xff; - buf[j++] = ((*ptr) >> 8) & 0xff; - buf[j++] = ((*ptr)) & 0xff; - ptr++; - } - jbuf = (JSAMPROW *) (&buf); - jpeg_write_scanlines(&cinfo, jbuf, 1); + unsigned int i, j; + + /* convert scaline from ARGB to RGB packed */ + ptr = ((const int *)data) + cinfo.next_scanline * w; + for (j = 0, i = 0; i < w; i++) + { + buf[j++] = ((*ptr) >> 16) & 0xff; + buf[j++] = ((*ptr) >> 8) & 0xff; + buf[j++] = ((*ptr)) & 0xff; + ptr++; + } + jbuf = (JSAMPROW *)(&buf); + jpeg_write_scanlines(&cinfo, jbuf, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); - _eet_memfile_write_close(f); *size = sz; return d; } static void * -eet_data_image_jpeg_alpha_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha, int quality) +eet_data_image_jpeg_alpha_convert(int *size, + const void *data, + unsigned int w, + unsigned int h, + int alpha, + int quality) { unsigned char *d1, *d2; unsigned char *d; int *header; int sz1, sz2; - (void) alpha; /* unused */ + (void)alpha; /* unused */ - if (words_bigendian == -1) + if (_eet_image_words_bigendian == -1) { - unsigned long int v; + unsigned long int v; - v = htonl(0x12345678); - if (v == 0x12345678) words_bigendian = 1; - else words_bigendian = 0; + v = htonl(0x12345678); + if (v == 0x12345678) + _eet_image_words_bigendian = 1; + else + _eet_image_words_bigendian = 0; } - { - const int *ptr; - void *d = NULL; - size_t sz = 0; - struct _JPEG_error_mgr jerr; - JSAMPROW *jbuf; - struct jpeg_compress_struct cinfo; - FILE *f; - unsigned char *buf; - - f = _eet_memfile_write_open(&d, &sz); - if (!f) return NULL; - - buf = alloca(3 * w); - - cinfo.err = jpeg_std_error(&(jerr.pub)); - jerr.pub.error_exit = _JPEGFatalErrorHandler; - jerr.pub.emit_message = _JPEGErrorHandler2; - jerr.pub.output_message = _JPEGErrorHandler; - if (setjmp(jerr.setjmp_buffer)) - { - jpeg_destroy_compress(&cinfo); - _eet_memfile_write_close(f); - if (d) free(d); - return NULL; - } - jpeg_create_compress(&cinfo); - jpeg_stdio_dest(&cinfo, f); - cinfo.image_width = w; - cinfo.image_height = h; - cinfo.input_components = 3; - cinfo.in_color_space = JCS_RGB; - jpeg_set_defaults(&cinfo); - jpeg_set_quality(&cinfo, quality, TRUE); - if (quality >= 90) - { - cinfo.comp_info[0].h_samp_factor = 1; - cinfo.comp_info[0].v_samp_factor = 1; - cinfo.comp_info[1].h_samp_factor = 1; - cinfo.comp_info[1].v_samp_factor = 1; - cinfo.comp_info[2].h_samp_factor = 1; - cinfo.comp_info[2].v_samp_factor = 1; - } - jpeg_start_compress(&cinfo, TRUE); - - ptr = data; - while (cinfo.next_scanline < cinfo.image_height) - { - unsigned int i, j; - - /* convert scaline from ARGB to RGB packed */ - for (j = 0, i = 0; i < w; i++) - { - buf[j++] = ((*ptr) >> 16) & 0xff; - buf[j++] = ((*ptr) >> 8) & 0xff; - buf[j++] = ((*ptr)) & 0xff; - ptr++; - } - jbuf = (JSAMPROW *) (&buf); - jpeg_write_scanlines(&cinfo, jbuf, 1); - } - - jpeg_finish_compress(&cinfo); - jpeg_destroy_compress(&cinfo); - - _eet_memfile_write_close(f); - d1 = d; - sz1 = sz; - } - { - const int *ptr; - void *d = NULL; - size_t sz = 0; - struct _JPEG_error_mgr jerr; - JSAMPROW *jbuf; - struct jpeg_compress_struct cinfo; - FILE *f; - unsigned char *buf; - - f = _eet_memfile_write_open(&d, &sz); - if (!f) - { - free(d1); - return NULL; - } - - buf = alloca(3 * w); - - cinfo.err = jpeg_std_error(&(jerr.pub)); - jerr.pub.error_exit = _JPEGFatalErrorHandler; - jerr.pub.emit_message = _JPEGErrorHandler2; - jerr.pub.output_message = _JPEGErrorHandler; - if (setjmp(jerr.setjmp_buffer)) - { - jpeg_destroy_compress(&cinfo); - _eet_memfile_write_close(f); - if (d) free(d); - free(d1); - return NULL; - } - jpeg_create_compress(&cinfo); - jpeg_stdio_dest(&cinfo, f); - cinfo.image_width = w; - cinfo.image_height = h; - cinfo.input_components = 1; - cinfo.in_color_space = JCS_GRAYSCALE; - jpeg_set_defaults(&cinfo); - jpeg_set_quality(&cinfo, quality, TRUE); - if (quality >= 90) - { - cinfo.comp_info[0].h_samp_factor = 1; - cinfo.comp_info[0].v_samp_factor = 1; - cinfo.comp_info[1].h_samp_factor = 1; - cinfo.comp_info[1].v_samp_factor = 1; - cinfo.comp_info[2].h_samp_factor = 1; - cinfo.comp_info[2].v_samp_factor = 1; - } - jpeg_start_compress(&cinfo, TRUE); - - ptr = data; - while (cinfo.next_scanline < cinfo.image_height) - { - unsigned int i, j; - - /* convert scaline from ARGB to RGB packed */ - for (j = 0, i = 0; i < w; i++) - { - buf[j++] = ((*ptr) >> 24) & 0xff; - ptr++; - } - jbuf = (JSAMPROW *) (&buf); - jpeg_write_scanlines(&cinfo, jbuf, 1); - } - - jpeg_finish_compress(&cinfo); - jpeg_destroy_compress(&cinfo); - - _eet_memfile_write_close(f); - d2 = d; - sz2 = sz; - } + { + const int *ptr; + void *dst = NULL; + size_t sz = 0; + struct _JPEG_error_mgr jerr; + JSAMPROW *jbuf; + struct jpeg_compress_struct cinfo; + unsigned char *buf; + + buf = alloca(3 * w); + + cinfo.err = jpeg_std_error(&(jerr.pub)); + jerr.pub.error_exit = _JPEGFatalErrorHandler; + jerr.pub.emit_message = _JPEGErrorHandler2; + jerr.pub.output_message = _JPEGErrorHandler; + if (setjmp(jerr.setjmp_buffer)) + return NULL; + + jpeg_create_compress(&cinfo); + if (eet_jpeg_membuf_dst(&cinfo, &dst, &sz)) + { + jpeg_destroy_compress(&cinfo); + return NULL; + } + + cinfo.image_width = w; + cinfo.image_height = h; + cinfo.input_components = 3; + cinfo.in_color_space = JCS_RGB; + cinfo.optimize_coding = FALSE; + cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss) + if (quality < 60) cinfo.dct_method = JDCT_IFAST; + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, quality, TRUE); + if (quality >= 90) + { + cinfo.comp_info[0].h_samp_factor = 1; + cinfo.comp_info[0].v_samp_factor = 1; + cinfo.comp_info[1].h_samp_factor = 1; + cinfo.comp_info[1].v_samp_factor = 1; + cinfo.comp_info[2].h_samp_factor = 1; + cinfo.comp_info[2].v_samp_factor = 1; + } + + jpeg_start_compress(&cinfo, TRUE); + + while (cinfo.next_scanline < cinfo.image_height) + { + unsigned int i, j; + + ptr = ((const int *)data) + cinfo.next_scanline * w; + /* convert scaline from ARGB to RGB packed */ + for (j = 0, i = 0; i < w; i++) + { + buf[j++] = ((*ptr) >> 16) & 0xff; + buf[j++] = ((*ptr) >> 8) & 0xff; + buf[j++] = ((*ptr)) & 0xff; + ptr++; + } + jbuf = (JSAMPROW *)(&buf); + jpeg_write_scanlines(&cinfo, jbuf, 1); + } + + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + d1 = dst; + sz1 = sz; + } + { + const int *ptr; + void *dst = NULL; + size_t sz = 0; + struct _JPEG_error_mgr jerr; + JSAMPROW *jbuf; + struct jpeg_compress_struct cinfo; + unsigned char *buf; + + buf = alloca(3 * w); + + cinfo.err = jpeg_std_error(&(jerr.pub)); + jerr.pub.error_exit = _JPEGFatalErrorHandler; + jerr.pub.emit_message = _JPEGErrorHandler2; + jerr.pub.output_message = _JPEGErrorHandler; + if (setjmp(jerr.setjmp_buffer)) + { + free(d1); + return NULL; + } + + jpeg_create_compress(&cinfo); + if (eet_jpeg_membuf_dst(&cinfo, &dst, &sz)) + { + jpeg_destroy_compress(&cinfo); + free(d1); + return NULL; + } + + cinfo.image_width = w; + cinfo.image_height = h; + cinfo.input_components = 1; + cinfo.in_color_space = JCS_GRAYSCALE; + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, quality, TRUE); + if (quality >= 90) + { + cinfo.comp_info[0].h_samp_factor = 1; + cinfo.comp_info[0].v_samp_factor = 1; + cinfo.comp_info[1].h_samp_factor = 1; + cinfo.comp_info[1].v_samp_factor = 1; + cinfo.comp_info[2].h_samp_factor = 1; + cinfo.comp_info[2].v_samp_factor = 1; + } + + jpeg_start_compress(&cinfo, TRUE); + + while (cinfo.next_scanline < cinfo.image_height) + { + unsigned int i, j; + + ptr = ((const int *)data) + cinfo.next_scanline * w; + /* convert scaline from ARGB to RGB packed */ + for (j = 0, i = 0; i < w; i++) + { + buf[j++] = ((*ptr) >> 24) & 0xff; + ptr++; + } + jbuf = (JSAMPROW *)(&buf); + jpeg_write_scanlines(&cinfo, jbuf, 1); + } + + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + d2 = dst; + sz2 = sz; + } d = malloc(12 + sz1 + sz2); if (!d) { - free(d1); - free(d2); - return NULL; + free(d1); + free(d2); + return NULL; } + header = (int *)d; header[0] = 0xbeeff00d; header[1] = sz1; header[2] = sz2; - if (words_bigendian) + if (_eet_image_words_bigendian) { - int i; + int i; - for (i = 0; i < 3; i++) SWAP32(header[i]); + for (i = 0; i < 3; i++) SWAP32(header[i]); } + memcpy(d + 12, d1, sz1); memcpy(d + 12 + sz1, d2, sz2); @@ -775,45 +1087,84 @@ eet_data_image_jpeg_alpha_convert(int *size, const void *data, unsigned int w, u } EAPI int -eet_data_image_write(Eet_File *ef, const char *name, - const void *data, unsigned int w, unsigned int h, int alpha, - int compress, int quality, int lossy) +eet_data_image_write_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + const void *data, + unsigned int w, + unsigned int h, + int alpha, + int comp, + int quality, + int lossy) { void *d = NULL; int size = 0; - d = eet_data_image_encode(data, &size, w, h, alpha, compress, quality, lossy); + d = eet_data_image_encode(data, &size, w, h, alpha, comp, quality, lossy); if (d) { - int v; + int v; - v = eet_write(ef, name, d, size, 0); - free(d); - return v; + v = eet_write_cipher(ef, name, d, size, 0, cipher_key); + free(d); + return v; } + return 0; } +EAPI int +eet_data_image_write(Eet_File *ef, + const char *name, + const void *data, + unsigned int w, + unsigned int h, + int alpha, + int comp, + int quality, + int lossy) +{ + return eet_data_image_write_cipher(ef, + name, + NULL, + data, + w, + h, + alpha, + comp, + quality, + lossy); +} + EAPI void * -eet_data_image_read(Eet_File *ef, const char *name, - unsigned int *w, unsigned int *h, int *alpha, - int *compress, int *quality, int *lossy) +eet_data_image_read_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + unsigned int *w, + unsigned int *h, + int *alpha, + int *comp, + int *quality, + int *lossy) { unsigned int *d = NULL; - void *data; - int size; - int free_data = 0; + void *data = NULL; + int free_data = 0; + int size; + if (!cipher_key) + data = (void *)eet_read_direct(ef, name, &size); - data = (void *)eet_read_direct(ef, name, &size); if (!data) { - data = eet_read(ef, name, &size); - free_data = 1; + data = eet_read_cipher(ef, name, &size, cipher_key); + free_data = 1; + if (!data) + return NULL; } - if (!data) return NULL; - d = eet_data_image_decode(data, size, w, h, alpha, compress, quality, lossy); + d = eet_data_image_decode(data, size, w, h, alpha, comp, quality, lossy); if (free_data) free(data); @@ -821,26 +1172,54 @@ eet_data_image_read(Eet_File *ef, const char *name, return d; } +EAPI void * +eet_data_image_read(Eet_File *ef, + const char *name, + unsigned int *w, + unsigned int *h, + int *alpha, + int *comp, + int *quality, + int *lossy) +{ + return eet_data_image_read_cipher(ef, name, NULL, w, h, alpha, + comp, quality, lossy); +} + EAPI int -eet_data_image_read_to_surface(Eet_File *ef, const char *name, unsigned int src_x, unsigned int src_y, - unsigned int *d, unsigned int w, unsigned int h, unsigned int row_stride, - int *alpha, int *compress, int *quality, int *lossy) +eet_data_image_read_to_surface_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + unsigned int src_x, + unsigned int src_y, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride, + int *alpha, + int *comp, + int *quality, + int *lossy) { - void *data; - int size; - int free_data = 0; - int res = 1; + void *data = NULL; + int free_data = 0; + int res = 1; + int size; + if (!cipher_key) + data = (void *)eet_read_direct(ef, name, &size); - data = (void *)eet_read_direct(ef, name, &size); if (!data) { - data = eet_read(ef, name, &size); - free_data = 1; + data = eet_read_cipher(ef, name, &size, cipher_key); + free_data = 1; + if (!data) + return 0; } - if (!data) return 0; - res = eet_data_image_decode_to_surface(data, size, src_x, src_y, d, w, h, row_stride, alpha, compress, quality, lossy); + res = eet_data_image_decode_to_surface(data, size, src_x, src_y, d, + w, h, row_stride, alpha, + comp, quality, lossy); if (free_data) free(data); @@ -849,307 +1228,654 @@ eet_data_image_read_to_surface(Eet_File *ef, const char *name, unsigned int src_ } EAPI int -eet_data_image_header_read(Eet_File *ef, const char *name, - unsigned int *w, unsigned int *h, int *alpha, - int *compress, int *quality, int *lossy) +eet_data_image_read_to_surface(Eet_File *ef, + const char *name, + unsigned int src_x, + unsigned int src_y, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride, + int *alpha, + int *comp, + int *quality, + int *lossy) +{ + return eet_data_image_read_to_surface_cipher(ef, name, NULL, + src_x, src_y, d, + w, h, row_stride, + alpha, comp, quality, + lossy); +} + +EAPI int +eet_data_image_header_read_cipher(Eet_File *ef, + const char *name, + const char *cipher_key, + unsigned int *w, + unsigned int *h, + int *alpha, + int *comp, + int *quality, + int *lossy) { - void *data = NULL; - int size = 0; - int d; - int free_data = 0; + void *data = NULL; + int size = 0; + int free_data = 0; + int d; + + if (!cipher_key) + data = (void *)eet_read_direct(ef, name, &size); - data = (void *)eet_read_direct(ef, name, &size); if (!data) { - data = eet_read(ef, name, &size); - free_data = 1; + data = eet_read_cipher(ef, name, &size, cipher_key); + free_data = 1; + if (!data) + return 0; } - if (!data) return 0; - d = eet_data_image_header_decode(data, size, w, h, alpha, compress, quality, lossy); + d = eet_data_image_header_decode(data, size, w, h, alpha, + comp, quality, lossy); if (free_data) free(data); return d; } +EAPI int +eet_data_image_header_read(Eet_File *ef, + const char *name, + unsigned int *w, + unsigned int *h, + int *alpha, + int *comp, + int *quality, + int *lossy) +{ + return eet_data_image_header_read_cipher(ef, name, NULL, + w, h, alpha, + comp, quality, lossy); +} + EAPI void * -eet_data_image_encode(const void *data, int *size_ret, unsigned int w, unsigned int h, int alpha, int compress, int quality, int lossy) +eet_data_image_encode_cipher(const void *data, + const char *cipher_key, + unsigned int w, + unsigned int h, + int alpha, + int comp, + int quality, + int lossy, + int *size_ret) { void *d = NULL; + void *ciphered_d = NULL; + unsigned int ciphered_sz = 0; int size = 0; if (lossy == 0) { - if (compress > 0) - d = eet_data_image_lossless_compressed_convert(&size, data, w, h, alpha, compress); - - /* eet_data_image_lossless_compressed_convert will refuse to compress something - if the result is bigger than the entry. */ - if (compress <= 0 || d == NULL) - d = eet_data_image_lossless_convert(&size, data, w, h, alpha); + if (comp > 0) + d = eet_data_image_lossless_compressed_convert(&size, data, + w, h, alpha, comp); + + /* eet_data_image_lossless_compressed_convert will refuse to compress something + if the result is bigger than the entry. */ + if (comp <= 0 || !d) + d = eet_data_image_lossless_convert(&size, data, w, h, alpha); } else { - if (!alpha) - d = eet_data_image_jpeg_convert(&size, data, w, h, alpha, quality); - else - d = eet_data_image_jpeg_alpha_convert(&size, data, w, h, alpha, quality); + if (!alpha) + d = eet_data_image_jpeg_convert(&size, data, w, h, alpha, quality); + else + d = eet_data_image_jpeg_alpha_convert(&size, data, + w, h, alpha, quality); + } + + if (cipher_key) + { + if(!eet_cipher(d, size, cipher_key, strlen(cipher_key), &ciphered_d, + &ciphered_sz)) + { + if (d) + free(d); + + d = ciphered_d; + size = ciphered_sz; + } + else + if (ciphered_d) + free(ciphered_d); } - if (size_ret) *size_ret = size; + + if (size_ret) + *size_ret = size; + return d; } +EAPI void * +eet_data_image_encode(const void *data, + int *size_ret, + unsigned int w, + unsigned int h, + int alpha, + int comp, + int quality, + int lossy) +{ + return eet_data_image_encode_cipher(data, NULL, w, h, alpha, + comp, quality, lossy, size_ret); +} + EAPI int -eet_data_image_header_decode(const void *data, int size, unsigned int *w, unsigned int *h, int *alpha, int *compress, int *quality, int *lossy) +eet_data_image_header_decode_cipher(const void *data, + const char *cipher_key, + int size, + unsigned int *w, + unsigned int *h, + int *alpha, + int *comp, + int *quality, + int *lossy) { int header[8]; + void *deciphered_d = NULL; + unsigned int deciphered_sz = 0; - if (words_bigendian == -1) + if (cipher_key) { - unsigned long int v; + if (!eet_decipher(data, size, cipher_key, strlen(cipher_key), + &deciphered_d, &deciphered_sz)) + { + data = deciphered_d; + size = deciphered_sz; + } + else + if (deciphered_d) + free(deciphered_d); + } - v = htonl(0x12345678); - if (v == 0x12345678) words_bigendian = 1; - else words_bigendian = 0; + if (_eet_image_words_bigendian == -1) + { + unsigned long int v; + + v = htonl(0x12345678); + if (v == 0x12345678) + _eet_image_words_bigendian = 1; + else + _eet_image_words_bigendian = 0; } - if (size < 32) return 0; + if (size < 32) + return 0; memcpy(header, data, 32); - if (words_bigendian) + if (_eet_image_words_bigendian) { - int i; + int i; - for (i = 0; i < 8; i++) SWAP32(header[i]); + for (i = 0; i < 8; i++) SWAP32(header[i]); } + if ((unsigned)header[0] == 0xac1dfeed) { - int iw, ih, al, cp; - - iw = header[1]; - ih = header[2]; - al = header[3]; - cp = header[4]; - if ((iw < 1) || (ih < 1) || (iw > 8192) || (ih > 8192)) return 0; - if ((cp == 0) && (size < ((iw * ih * 4) + 32))) return 0; - if (w) *w = iw; - if (h) *h = ih; - if (alpha) *alpha = al ? 1 : 0; - if (compress) *compress = cp; - if (lossy) *lossy = 0; - if (quality) *quality = 100; - return 1; + int iw, ih, al, cp; + + iw = header[1]; + ih = header[2]; + al = header[3]; + cp = header[4]; + if ((iw < 1) || (ih < 1) || (iw > 8192) || (ih > 8192)) + return 0; + + if ((cp == 0) && (size < ((iw * ih * 4) + 32))) + return 0; + + if (w) + *w = iw; + + if (h) + *h = ih; + + if (alpha) + *alpha = al ? 1 : 0; + + if (comp) + *comp = cp; + + if (lossy) + *lossy = 0; + + if (quality) + *quality = 100; + + return 1; } else if ((unsigned)header[0] == 0xbeeff00d) { - unsigned int iw = 0, ih = 0; - unsigned const char *dt; - int sz1, sz2; - int ok; - - sz1 = header[1]; - sz2 = header[2]; - dt = data; - dt += 12; - ok = eet_data_image_jpeg_header_decode(dt, sz1, &iw, &ih); - if (ok) - { - if (w) *w = iw; - if (h) *h = ih; - if (alpha) *alpha = 1; - if (compress) *compress = 0; - if (lossy) *lossy = 1; - if (quality) *quality = 75; - return 1; - } + unsigned int iw = 0, ih = 0; + unsigned const char *dt; + int sz1; + int ok; + + sz1 = header[1]; +/* sz2 = header[2]; */ + dt = data; + dt += 12; + ok = eet_data_image_jpeg_header_decode(dt, sz1, &iw, &ih); + if (ok) + { + if (w) + *w = iw; + + if (h) + *h = ih; + + if (alpha) + *alpha = 1; + + if (comp) + *comp = 0; + + if (lossy) + *lossy = 1; + + if (quality) + *quality = 75; + + return 1; + } } else { - unsigned int iw = 0, ih = 0; - int ok; - - ok = eet_data_image_jpeg_header_decode(data, size, &iw, &ih); - if (ok) - { - if (w) *w = iw; - if (h) *h = ih; - if (alpha) *alpha = 0; - if (compress) *compress = 0; - if (lossy) *lossy = 1; - if (quality) *quality = 75; - return 1; - } + unsigned int iw = 0, ih = 0; + int ok; + + ok = eet_data_image_jpeg_header_decode(data, size, &iw, &ih); + if (ok) + { + if (w) + *w = iw; + + if (h) + *h = ih; + + if (alpha) + *alpha = 0; + + if (comp) + *comp = 0; + + if (lossy) + *lossy = 1; + + if (quality) + *quality = 75; + + return 1; + } } + return 0; } +EAPI int +eet_data_image_header_decode(const void *data, + int size, + unsigned int *w, + unsigned int *h, + int *alpha, + int *comp, + int *quality, + int *lossy) +{ + return eet_data_image_header_decode_cipher(data, + NULL, + size, + w, + h, + alpha, + comp, + quality, + lossy); +} + static void -_eet_data_image_copy_buffer(const unsigned int *src, unsigned int src_x, unsigned int src_y, unsigned int src_w, - unsigned int *dst, unsigned int w, unsigned int h, unsigned int row_stride) +_eet_data_image_copy_buffer(const unsigned int *src, + unsigned int src_x, + unsigned int src_y, + unsigned int src_w, + unsigned int *dst, + unsigned int w, + unsigned int h, + unsigned int row_stride) { src += src_x + src_y * src_w; if (row_stride == src_w * 4 && w == src_w) - { - memcpy(dst, src, row_stride * h); - } + memcpy(dst, src, row_stride * h); else { - unsigned int *over = dst; - unsigned int y; + unsigned int *over = dst; + unsigned int y; - for (y = 0; y < h; ++y, src += src_w, over += row_stride) - memcpy(over, src, w * 4); + for (y = 0; y < h; ++y, src += src_w, over += row_stride) + memcpy(over, src, w * 4); } } - static int -_eet_data_image_decode_inside(const void *data, int size, unsigned int src_x, unsigned int src_y, - unsigned int src_w, unsigned int src_h, - unsigned int *d, unsigned int w, unsigned int h, unsigned int row_stride, - int alpha, int compress, int quality, int lossy) +_eet_data_image_decode_inside(const void *data, + int size, + unsigned int src_x, + unsigned int src_y, + unsigned int src_w, + unsigned int src_h, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride, + int alpha, + int comp, + int quality, + int lossy) { if (lossy == 0 && quality == 100) { - unsigned int *body; - - body = ((unsigned int *)data) + 8; - if (!compress) - { - _eet_data_image_copy_buffer(body, src_x, src_y, src_w, d, w, h, row_stride); - } - else - { - if (src_h == h && src_w == w && row_stride == src_w * 4) - { - uLongf dlen; - - dlen = w * h * 4; - uncompress((Bytef *)d, &dlen, (Bytef *)body, - (uLongf)(size - 32)); - } - else - { - Bytef *dtmp; - uLongf dlen = src_w * src_h * 4; - - /* FIXME: This could create a huge alloc. So compressed data and tile could not always work. */ - dtmp = malloc(dlen); - if (!dtmp) return 0; - - uncompress(dtmp, &dlen, (Bytef *)body, (uLongf)(size - 32)); - - _eet_data_image_copy_buffer((unsigned int *) dtmp, src_x, src_y, src_w, d, w, h, row_stride); - - free(dtmp); - } - } - - /* Fix swapiness. */ - if (words_bigendian) - { - unsigned int x; - - for (x = 0; x < (w * h); x++) SWAP32(d[x]); - } + unsigned int *body; + + body = ((unsigned int *)data) + 8; + if (!comp) + _eet_data_image_copy_buffer(body, src_x, src_y, src_w, d, + w, h, row_stride); + else + { + if ((src_h == h) && (src_w == w) && (row_stride == src_w * 4)) + { + switch (comp) + { + case EET_COMPRESSION_VERYFAST: + case EET_COMPRESSION_SUPERFAST: + if (LZ4_uncompress((const char *)body, + (char *)d, w * h * 4) + != (size - 32)) return 0; + break; + default: + { + uLongf dlen = w * h * 4; + + if (uncompress((Bytef *)d, &dlen, (Bytef *)body, + (uLongf)(size - 32)) != Z_OK) + return 0; + } + break; + } + } + else + { + switch (comp) + { + case EET_COMPRESSION_VERYFAST: + case EET_COMPRESSION_SUPERFAST: + { + char *dtmp; + + dtmp = malloc(src_w * src_h * 4); + if (!dtmp) return 0; + if (LZ4_uncompress((const char *)body, + dtmp, w * h * 4) + != (size - 32)) + { + free(dtmp); + return 0; + } + _eet_data_image_copy_buffer((unsigned int *)dtmp, + src_x, src_y, src_w, d, + w, h, row_stride); + free(dtmp); + } + break; + default: + { + Bytef *dtmp; + uLongf dlen = src_w * src_h * 4; + + /* FIXME: This could create a huge alloc. So + compressed data and tile could not always work.*/ + dtmp = malloc(dlen); + if (!dtmp) return 0; + + if (uncompress(dtmp, &dlen, (Bytef *)body, + (uLongf)(size - 32)) != Z_OK) + { + free(dtmp); + return 0; + } + _eet_data_image_copy_buffer((unsigned int *)dtmp, + src_x, src_y, src_w, d, + w, h, row_stride); + free(dtmp); + } + } + } + } + /* Fix swapiness. */ + if (_eet_image_words_bigendian) + { + unsigned int x; + + for (x = 0; x < (w * h); x++) SWAP32(d[x]); + } } - else if (compress == 0 && lossy == 1) + else if (comp == 0 && lossy == 1) { - if (alpha) - { - unsigned const char *dt; - int header[8]; - int sz1, sz2; - - memcpy(header, data, 32); - if (words_bigendian) - { - int i; - - for (i = 0; i < 8; i++) SWAP32(header[i]); - } - - sz1 = header[1]; - sz2 = header[2]; - dt = data; - dt += 12; - - if (eet_data_image_jpeg_rgb_decode(dt, sz1, src_x, src_y, d, w, h, row_stride)) - { - dt += sz1; - if (!eet_data_image_jpeg_alpha_decode(dt, sz2, src_x, src_y, d, w, h, row_stride)) - return 0; - } - } - else - { - if (!eet_data_image_jpeg_rgb_decode(data, size, src_x, src_y, d, w, h, row_stride)) - return 0; - } + if (alpha) + { + unsigned const char *dt; + int header[8]; + int sz1, sz2; + + memcpy(header, data, 32); + if (_eet_image_words_bigendian) + { + int i; + + for (i = 0; i < 8; i++) SWAP32(header[i]); + } + + sz1 = header[1]; + sz2 = header[2]; + dt = data; + dt += 12; + + if (eet_data_image_jpeg_rgb_decode(dt, sz1, src_x, src_y, d, w, h, + row_stride)) + { + dt += sz1; + if (!eet_data_image_jpeg_alpha_decode(dt, sz2, src_x, src_y, + d, w, h, row_stride)) + return 0; + } + } + else if (!eet_data_image_jpeg_rgb_decode(data, size, src_x, src_y, d, w, + h, row_stride)) + return 0; } else - { - abort(); - } + abort(); return 1; } EAPI void * -eet_data_image_decode(const void *data, int size, unsigned int *w, unsigned int *h, int *alpha, int *compress, int *quality, int *lossy) +eet_data_image_decode_cipher(const void *data, + const char *cipher_key, + int size, + unsigned int *w, + unsigned int *h, + int *alpha, + int *comp, + int *quality, + int *lossy) { unsigned int *d = NULL; unsigned int iw, ih; int ialpha, icompress, iquality, ilossy; + void *deciphered_d = NULL; + unsigned int deciphered_sz = 0; + + if (cipher_key) + { + if (!eet_decipher(data, size, cipher_key, strlen(cipher_key), + &deciphered_d, &deciphered_sz)) + { + data = deciphered_d; + size = deciphered_sz; + } + else + if (deciphered_d) + free(deciphered_d); + } /* All check are done during header decode, this simplify the code a lot. */ - if (!eet_data_image_header_decode(data, size, &iw, &ih, &ialpha, &icompress, &iquality, &ilossy)) + if (!eet_data_image_header_decode(data, size, &iw, &ih, &ialpha, &icompress, + &iquality, &ilossy)) return NULL; d = malloc(iw * ih * 4); - if (!d) return NULL; + if (!d) + return NULL; - if (!_eet_data_image_decode_inside(data, size, 0, 0, iw, ih, d, iw, ih, iw * 4, ialpha, icompress, iquality, ilossy)) + if (!_eet_data_image_decode_inside(data, size, 0, 0, iw, ih, d, iw, ih, iw * + 4, ialpha, icompress, iquality, ilossy)) { - if (d) free(d); - return NULL; + free(d); + return NULL; } - if (w) *w = iw; - if (h) *h = ih; - if (alpha) *alpha = ialpha; - if (compress) *compress = icompress; - if (quality) *quality = iquality; - if (lossy) *lossy = ilossy; + if (w) + *w = iw; + + if (h) + *h = ih; + + if (alpha) + *alpha = ialpha; + + if (comp) + *comp = icompress; + + if (quality) + *quality = iquality; + + if (lossy) + *lossy = ilossy; return d; } +EAPI void * +eet_data_image_decode(const void *data, + int size, + unsigned int *w, + unsigned int *h, + int *alpha, + int *comp, + int *quality, + int *lossy) +{ + return eet_data_image_decode_cipher(data, NULL, size, w, h, + alpha, comp, quality, lossy); +} + EAPI int -eet_data_image_decode_to_surface(const void *data, int size, unsigned int src_x, unsigned int src_y, - unsigned int *d, unsigned int w, unsigned int h, unsigned int row_stride, - int *alpha, int *compress, int *quality, int *lossy) +eet_data_image_decode_to_surface_cipher(const void *data, + const char *cipher_key, + int size, + unsigned int src_x, + unsigned int src_y, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride, + int *alpha, + int *comp, + int *quality, + int *lossy) { unsigned int iw, ih; int ialpha, icompress, iquality, ilossy; + void *deciphered_d = NULL; + unsigned int deciphered_sz = 0; + + if (cipher_key) + { + if (!eet_decipher(data, size, cipher_key, strlen(cipher_key), + &deciphered_d, &deciphered_sz)) + { + data = deciphered_d; + size = deciphered_sz; + } + else + if (deciphered_d) + free(deciphered_d); + } /* All check are done during header decode, this simplify the code a lot. */ - if (!eet_data_image_header_decode(data, size, &iw, &ih, &ialpha, &icompress, &iquality, &ilossy)) + if (!eet_data_image_header_decode(data, size, &iw, &ih, &ialpha, &icompress, + &iquality, &ilossy)) + return 0; + + if (!d) + return 0; + + if (w * 4 > row_stride) return 0; - if (!d) return 0; - if (w * 4 > row_stride) return 0; - if (w > iw || h > ih) return 0; + if (w > iw || h > ih) + return 0; - if (!_eet_data_image_decode_inside(data, size, src_x, src_y, iw, ih, d, w, h, row_stride, ialpha, icompress, iquality, ilossy)) + if (!_eet_data_image_decode_inside(data, size, src_x, src_y, iw, ih, d, w, h, + row_stride, ialpha, icompress, iquality, + ilossy)) return 0; - if (alpha) *alpha = ialpha; - if (compress) *compress = icompress; - if (quality) *quality = iquality; - if (lossy) *lossy = ilossy; + if (alpha) + *alpha = ialpha; + + if (comp) + *comp = icompress; + + if (quality) + *quality = iquality; + + if (lossy) + *lossy = ilossy; return 1; } + +EAPI int +eet_data_image_decode_to_surface(const void *data, + int size, + unsigned int src_x, + unsigned int src_y, + unsigned int *d, + unsigned int w, + unsigned int h, + unsigned int row_stride, + int *alpha, + int *comp, + int *quality, + int *lossy) +{ + return eet_data_image_decode_to_surface_cipher(data, NULL, size, + src_x, src_y, d, + w, h, row_stride, + alpha, comp, quality, + lossy); +} + diff --git a/src/lib/eet_lib.c b/src/lib/eet_lib.c index a2775d4..32b55cf 100644 --- a/src/lib/eet_lib.c +++ b/src/lib/eet_lib.c @@ -1,10 +1,6 @@ -/* - * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 - */ - #ifdef HAVE_CONFIG_H # include -#endif +#endif /* ifdef HAVE_CONFIG_H */ #ifdef HAVE_ALLOCA_H # include @@ -15,187 +11,158 @@ #elif defined _MSC_VER # include # define alloca _alloca -#else +#else /* ifdef HAVE_ALLOCA_H */ # include # ifdef __cplusplus extern "C" -# endif -void *alloca (size_t); -#endif +# endif /* ifdef __cplusplus */ +void *alloca(size_t); +#endif /* ifdef HAVE_ALLOCA_H */ + +#ifdef _WIN32 +# include +#endif /* ifdef _WIN32 */ #include #include #include #include -#include #include #include #include #include -#include #include +#ifdef HAVE_UNISTD_H +# include +#endif /* ifdef HAVE_UNISTD_H */ + #ifdef HAVE_NETINET_IN_H # include -#endif - -#if defined(_WIN32) && ! defined(__CEGCC__) -# include -#endif +#endif /* ifdef HAVE_NETINET_IN_H */ #ifdef HAVE_EVIL # include -#endif - -#include "Eet.h" -#include "Eet_private.h" +#endif /* ifdef HAVE_EVIL */ -#ifdef HAVE_REALPATH -#undef HAVE_REALPATH -#endif +#include -#define EET_MAGIC_FILE 0x1ee7ff00 -#define EET_MAGIC_FILE_HEADER 0x1ee7ff01 +#ifdef HAVE_GNUTLS +# include +# include +#endif /* ifdef HAVE_GNUTLS */ -#define EET_MAGIC_FILE2 0x1ee70f42 +#ifdef HAVE_OPENSSL +# include +# include +#endif /* ifdef HAVE_OPENSSL */ -typedef struct _Eet_File_Header Eet_File_Header; -typedef struct _Eet_File_Node Eet_File_Node; -typedef struct _Eet_File_Directory Eet_File_Directory; - -struct _Eet_File -{ - char *path; - FILE *fp; - FILE *readfp; - Eet_File_Header *header; - const unsigned char *data; - Eet_Dictionary *ed; +#ifdef EINA_HAVE_THREADS +# ifdef HAVE_GNUTLS +GCRY_THREAD_OPTION_PTHREAD_IMPL; +# endif /* ifdef HAVE_GNUTLS */ +#endif /* ifdef EINA_HAVE_THREADS */ - int magic; - int references; +#include "Eet.h" +#include "Eet_private.h" - Eet_File_Mode mode; - int data_size; - time_t mtime; +#include "lz4.h" +#include "lz4hc.h" - unsigned char writes_pending : 1; - unsigned char delete_me_now : 1; -}; +#ifndef O_BINARY +# define O_BINARY 0 +#endif -struct _Eet_File_Header -{ - int magic; - Eet_File_Directory *directory; -}; +static Eet_Version _version = { VMAJ, VMIN, VMIC, VREV }; +EAPI Eet_Version *eet_version = &_version; -struct _Eet_File_Directory -{ - int size; - Eet_File_Node **nodes; -}; +#ifdef HAVE_REALPATH +# undef HAVE_REALPATH +#endif /* ifdef HAVE_REALPATH */ -struct _Eet_File_Node -{ - char *name; - void *data; - Eet_File_Node *next; /* FIXME: make buckets linked lists */ - - int offset; - int dictionary_offset; - int name_offset; - - int name_size; - int size; - int data_size; - - unsigned char free_name : 1; - unsigned char compression : 1; -}; - -#if 0 -/* Version 2 */ -/* NB: all int's are stored in network byte order on disk */ -/* file format: */ -int magic; /* magic number ie 0x1ee7ff00 */ -int num_directory_entries; /* number of directory entries to follow */ -int bytes_directory_entries; /* bytes of directory entries to follow */ -struct -{ - int offset; /* bytes offset into file for data chunk */ - int flags; /* flags - for now 0 = uncompressed, 1 = compressed */ - int size; /* size of the data chunk */ - int data_size; /* size of the (uncompressed) data chunk */ - int name_size; /* length in bytes of the name field */ - char name[name_size]; /* name string (variable length) and \0 terminated */ -} directory[num_directory_entries]; -/* and now startes the data stream... */ -#endif +#define EET_MAGIC_FILE 0x1ee7ff00 +#define EET_MAGIC_FILE_HEADER 0x1ee7ff01 -#if 0 -/* Version 3 */ -/* NB: all int's are stored in network byte order on disk */ -/* file format: */ -int magic; /* magic number ie 0x1ee70f42 */ -int num_directory_entries; /* number of directory entries to follow */ -int num_dictionary_entries; /* number of dictionary entries to follow */ -struct -{ - int data_offset; /* bytes offset into file for data chunk */ - int size; /* size of the data chunk */ - int data_size; /* size of the (uncompressed) data chunk */ - int name_offset; /* bytes offset into file for name string */ - int name_size; /* length in bytes of the name field */ - int flags; /* flags - for now 0 = uncompressed, 1 = compressed */ -} directory[num_directory_entries]; -struct -{ - int hash; - int offset; - int size; - int prev; - int next; -} dictionary[num_dictionary_entries]; -/* now start the string stream. */ -/* and right after them the data stream. */ -#endif +#define EET_MAGIC_FILE2 0x1ee70f42 -#define EET_FILE2_HEADER_COUNT 3 -#define EET_FILE2_DIRECTORY_ENTRY_COUNT 6 -#define EET_FILE2_DICTIONARY_ENTRY_COUNT 5 +#define EET_FILE2_HEADER_COUNT 3 +#define EET_FILE2_DIRECTORY_ENTRY_COUNT 6 +#define EET_FILE2_DICTIONARY_ENTRY_COUNT 5 -#define EET_FILE2_HEADER_SIZE (sizeof(int) * EET_FILE2_HEADER_COUNT) -#define EET_FILE2_DIRECTORY_ENTRY_SIZE (sizeof(int) * EET_FILE2_DIRECTORY_ENTRY_COUNT) -#define EET_FILE2_DICTIONARY_ENTRY_SIZE (sizeof(int) * EET_FILE2_DICTIONARY_ENTRY_COUNT) +#define EET_FILE2_HEADER_SIZE (sizeof(int) * \ + EET_FILE2_HEADER_COUNT) +#define EET_FILE2_DIRECTORY_ENTRY_SIZE (sizeof(int) * \ + EET_FILE2_DIRECTORY_ENTRY_COUNT) +#define EET_FILE2_DICTIONARY_ENTRY_SIZE (sizeof(int) * \ + EET_FILE2_DICTIONARY_ENTRY_COUNT) /* prototypes of internal calls */ -static Eet_File *eet_cache_find(const char *path, Eet_File **cache, int cache_num); -static void eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc); -static void eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc); -static int eet_string_match(const char *s1, const char *s2); +static Eet_File * +eet_cache_find(const char *path, + Eet_File **cache, + int cache_num); +static void +eet_cache_add(Eet_File *ef, + Eet_File ***cache, + int *cache_num, + int *cache_alloc); +static void +eet_cache_del(Eet_File *ef, + Eet_File ***cache, + int *cache_num, + int *cache_alloc); +static int +eet_string_match(const char *s1, + const char *s2); #if 0 /* Unused */ -static Eet_Error eet_flush(Eet_File *ef); -#endif -static Eet_Error eet_flush2(Eet_File *ef); -static Eet_File_Node *find_node_by_name(Eet_File *ef, const char *name); -static int read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len); +static Eet_Error +eet_flush(Eet_File *ef); +#endif /* if 0 */ +static Eet_Error + eet_flush2(Eet_File *ef); +static Eet_File_Node * + find_node_by_name(Eet_File *ef, + const char *name); +static int +read_data_from_disk(Eet_File *ef, + Eet_File_Node *efn, + void *buf, + int len); + +static Eet_Error +eet_internal_close(Eet_File *ef, + Eina_Bool locked); + +static Eina_Lock eet_cache_lock; + +#define LOCK_CACHE eina_lock_take(&eet_cache_lock) +#define UNLOCK_CACHE eina_lock_release(&eet_cache_lock) + +#define INIT_FILE(File) eina_lock_new(&File->file_lock) +#define LOCK_FILE(File) eina_lock_take(&File->file_lock) +#define UNLOCK_FILE(File) eina_lock_release(&File->file_lock) +#define DESTROY_FILE(File) eina_lock_free(&File->file_lock) /* cache. i don't expect this to ever be large, so arrays will do */ -static int eet_writers_num = 0; -static int eet_writers_alloc = 0; -static Eet_File **eet_writers = NULL; -static int eet_readers_num = 0; -static int eet_readers_alloc = 0; -static Eet_File **eet_readers = NULL; -static int eet_initcount = 0; +static int eet_writers_num = 0; +static int eet_writers_alloc = 0; +static Eet_File **eet_writers = NULL; +static int eet_readers_num = 0; +static int eet_readers_alloc = 0; +static Eet_File **eet_readers = NULL; +static int eet_init_count = 0; + +/* log domain variable */ +int _eet_log_dom_global = -1; /* Check to see its' an eet file pointer */ static inline int eet_check_pointer(const Eet_File *ef) { - if ((!ef) || (ef->magic != EET_MAGIC_FILE)) - return 1; - return 0; + if ((!ef) || (ef->magic != EET_MAGIC_FILE)) + return 1; + + return 0; } static inline int @@ -203,37 +170,41 @@ eet_check_header(const Eet_File *ef) { if (!ef->header) return 1; + if (!ef->header->directory) return 1; + return 0; } static inline int -eet_test_close(int test, Eet_File *ef) +eet_test_close(int test, + Eet_File *ef) { if (test) { - ef->delete_me_now = 1; - eet_close(ef); + ef->delete_me_now = 1; + eet_internal_close(ef, EINA_TRUE); } + return test; } /* find an eet file in the currently in use cache */ static Eet_File * -eet_cache_find(const char *path, Eet_File **cache, int cache_num) +eet_cache_find(const char *path, + Eet_File **cache, + int cache_num) { int i; /* walk list */ for (i = 0; i < cache_num; i++) { - /* if matches real path - return it */ - if (eet_string_match(cache[i]->path, path)) - { - if (!cache[i]->delete_me_now) - return cache[i]; - } + /* if matches real path - return it */ + if (eet_string_match(cache[i]->path, path)) + if (!cache[i]->delete_me_now) + return cache[i]; } /* not found */ @@ -241,34 +212,38 @@ eet_cache_find(const char *path, Eet_File **cache, int cache_num) } /* add to end of cache */ +/* this should only be called when the cache lock is already held */ static void -eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc) +eet_cache_add(Eet_File *ef, + Eet_File ***cache, + int *cache_num, + int *cache_alloc) { - Eet_File **new_cache; - int new_cache_num; - int new_cache_alloc; + Eet_File **new_cache; + int new_cache_num; + int new_cache_alloc; new_cache_num = *cache_num; if (new_cache_num >= 64) /* avoid fd overruns - limit to 128 (most recent) in the cache */ { - Eet_File *del_ef = NULL; - int i; + Eet_File *del_ef = NULL; + int i; - new_cache = *cache; - for (i = 0; i < new_cache_num; i++) - { - if (new_cache[i]->references == 0) - { - del_ef = new_cache[i]; - break; - } - } + new_cache = *cache; + for (i = 0; i < new_cache_num; i++) + { + if (new_cache[i]->references == 0) + { + del_ef = new_cache[i]; + break; + } + } - if (del_ef) - { - del_ef->delete_me_now = 1; - eet_close(del_ef); - } + if (del_ef) + { + del_ef->delete_me_now = 1; + eet_internal_close(del_ef, EINA_TRUE); + } } new_cache = *cache; @@ -277,14 +252,15 @@ eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc) new_cache_num++; if (new_cache_num > new_cache_alloc) { - new_cache_alloc += 16; - new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *)); - if (!new_cache) - { - fprintf(stderr, "BAD ERROR! Eet realloc of cache list failed. Abort\n"); - abort(); - } + new_cache_alloc += 16; + new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *)); + if (!new_cache) + { + CRIT("BAD ERROR! Eet realloc of cache list failed. Abort"); + abort(); + } } + new_cache[new_cache_num - 1] = ef; *cache = new_cache; *cache_num = new_cache_num; @@ -292,8 +268,12 @@ eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc) } /* delete from cache */ +/* this should only be called when the cache lock is already held */ static void -eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc) +eet_cache_del(Eet_File *ef, + Eet_File ***cache, + int *cache_num, + int *cache_alloc) { Eet_File **new_cache; int new_cache_num, new_cache_alloc; @@ -307,8 +287,8 @@ eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc) for (i = 0; i < new_cache_num; i++) { - if (new_cache[i] == ef) - break; + if (new_cache[i] == ef) + break; } if (i >= new_cache_num) @@ -318,24 +298,25 @@ eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc) for (j = i; j < new_cache_num; j++) new_cache[j] = new_cache[j + 1]; - if (new_cache_num < (new_cache_alloc - 16)) - { - new_cache_alloc -= 16; - if (new_cache_num > 0) - { - new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *)); - if (!new_cache) - { - fprintf(stderr, "BAD ERROR! Eet realloc of cache list failed. Abort\n"); - abort(); - } - } - else - { - free(new_cache); - new_cache = NULL; - } + if (new_cache_num <= (new_cache_alloc - 16)) + { + new_cache_alloc -= 16; + if (new_cache_num > 0) + { + new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *)); + if (!new_cache) + { + CRIT("BAD ERROR! Eet realloc of cache list failed. Abort"); + abort(); + } + } + else + { + free(new_cache); + new_cache = NULL; + } } + *cache = new_cache; *cache_num = new_cache_num; *cache_alloc = new_cache_alloc; @@ -343,47 +324,63 @@ eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc) /* internal string match. null friendly, catches same ptr */ static int -eet_string_match(const char *s1, const char *s2) +eet_string_match(const char *s1, + const char *s2) { /* both null- no match */ - if ((!s1) || (!s2)) return 0; - if (s1 == s2) return 1; - return (!strcmp(s1, s2)); + if ((!s1) || (!s2)) + return 0; + + if (s1 == s2) + return 1; + + return !strcmp(s1, s2); } /* flush out writes to a v2 eet file */ static Eet_Error eet_flush2(Eet_File *ef) { - Eet_File_Node *efn; - Eet_Error error = EET_ERROR_NONE; - int head[EET_FILE2_HEADER_COUNT]; - int num_directory_entries = 0; - int num_dictionary_entries = 0; - int bytes_directory_entries = 0; - int bytes_dictionary_entries = 0; - int bytes_strings = 0; - int data_offset = 0; - int strings_offset = 0; - int num; - int i; - int j; + Eet_File_Node *efn; + FILE *fp; + Eet_Error error = EET_ERROR_NONE; + int head[EET_FILE2_HEADER_COUNT]; + int num_directory_entries = 0; + int num_dictionary_entries = 0; + int bytes_directory_entries = 0; + int bytes_dictionary_entries = 0; + int bytes_strings = 0; + int data_offset = 0; + int strings_offset = 0; + int num; + int i; + int j; if (eet_check_pointer(ef)) return EET_ERROR_BAD_OBJECT; + if (eet_check_header(ef)) return EET_ERROR_EMPTY; - if ((ef->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE)) - return EET_ERROR_NOT_WRITABLE; + if (!ef->writes_pending) return EET_ERROR_NONE; - if (ef->mode == EET_FILE_MODE_READ_WRITE && ef->fp == NULL) + + if ((ef->mode == EET_FILE_MODE_READ_WRITE) + || (ef->mode == EET_FILE_MODE_WRITE)) { - unlink(ef->path); - ef->fp = fopen(ef->path, "wb"); - if (!ef->fp) return EET_ERROR_NOT_WRITABLE; - fcntl(fileno(ef->fp), F_SETFD, FD_CLOEXEC); + int fd; + + /* opening for write - delete old copy of file right away */ + unlink(ef->path); + fd = open(ef->path, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, S_IRUSR | S_IWUSR); + fp = fdopen(fd, "wb"); + if (!fp) + return EET_ERROR_NOT_WRITABLE; + + fcntl(fd, F_SETFD, FD_CLOEXEC); } + else + return EET_ERROR_NOT_WRITABLE; /* calculate string base offset and data base offset */ num = (1 << ef->header->directory->size); @@ -404,12 +401,15 @@ eet_flush2(Eet_File *ef) } /* calculate section bytes size */ - bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE; - bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries; + bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * + num_directory_entries + EET_FILE2_HEADER_SIZE; + bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * + num_dictionary_entries; /* calculate per entry offset */ strings_offset = bytes_directory_entries + bytes_dictionary_entries; - data_offset = bytes_directory_entries + bytes_dictionary_entries + bytes_strings; + data_offset = bytes_directory_entries + bytes_dictionary_entries + + bytes_strings; for (i = 0; i < num; ++i) { @@ -428,52 +428,55 @@ eet_flush2(Eet_File *ef) ef->ed->offset = strings_offset; /* go thru and write the header */ - head[0] = (int) htonl ((unsigned int) EET_MAGIC_FILE2); - head[1] = (int) htonl ((unsigned int) num_directory_entries); - head[2] = (int) htonl ((unsigned int) num_dictionary_entries); + head[0] = (int)htonl((unsigned int)EET_MAGIC_FILE2); + head[1] = (int)htonl((unsigned int)num_directory_entries); + head[2] = (int)htonl((unsigned int)num_dictionary_entries); - fseek(ef->fp, 0, SEEK_SET); - if (fwrite(head, sizeof (head), 1, ef->fp) != 1) + fseek(fp, 0, SEEK_SET); + if (fwrite(head, sizeof (head), 1, fp) != 1) goto write_error; /* write directories entry */ - j = 0; for (i = 0; i < num; i++) { for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) { - int ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT]; + unsigned int flag; + int ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT]; + + flag = (efn->alias << 2) | (efn->ciphered << 1) | efn->compression; + flag |= efn->compression_type << 3; - ibuf[0] = (int) htonl ((unsigned int) efn->offset); - ibuf[1] = (int) htonl ((unsigned int) efn->size); - ibuf[2] = (int) htonl ((unsigned int) efn->data_size); - ibuf[3] = (int) htonl ((unsigned int) efn->name_offset); - ibuf[4] = (int) htonl ((unsigned int) efn->name_size); - ibuf[5] = (int) htonl ((unsigned int) efn->compression); + ibuf[0] = (int)htonl((unsigned int)efn->offset); + ibuf[1] = (int)htonl((unsigned int)efn->size); + ibuf[2] = (int)htonl((unsigned int)efn->data_size); + ibuf[3] = (int)htonl((unsigned int)efn->name_offset); + ibuf[4] = (int)htonl((unsigned int)efn->name_size); + ibuf[5] = (int)htonl((unsigned int)flag); - if (fwrite(ibuf, sizeof(ibuf), 1, ef->fp) != 1) + if (fwrite(ibuf, sizeof(ibuf), 1, fp) != 1) goto write_error; } } - /* write dictionnary */ + /* write dictionary */ if (ef->ed) { - int offset = strings_offset; + int offset = strings_offset; for (j = 0; j < ef->ed->count; ++j) { - int sbuf[EET_FILE2_DICTIONARY_ENTRY_COUNT]; + int sbuf[EET_FILE2_DICTIONARY_ENTRY_COUNT]; - sbuf[0] = (int) htonl ((unsigned int) ef->ed->all[j].hash); - sbuf[1] = (int) htonl ((unsigned int) offset); - sbuf[2] = (int) htonl ((unsigned int) ef->ed->all[j].len); - sbuf[3] = (int) htonl ((unsigned int) ef->ed->all[j].prev); - sbuf[4] = (int) htonl ((unsigned int) ef->ed->all[j].next); + sbuf[0] = (int)htonl((unsigned int)ef->ed->all[j].hash); + sbuf[1] = (int)htonl((unsigned int)offset); + sbuf[2] = (int)htonl((unsigned int)ef->ed->all[j].len); + sbuf[3] = (int)htonl((unsigned int)ef->ed->all[j].prev); + sbuf[4] = (int)htonl((unsigned int)ef->ed->all[j].next); offset += ef->ed->all[j].len; - if (fwrite(sbuf, sizeof (sbuf), 1, ef->fp) != 1) + if (fwrite(sbuf, sizeof (sbuf), 1, fp) != 1) goto write_error; } } @@ -483,350 +486,426 @@ eet_flush2(Eet_File *ef) { for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) { - if (fwrite(efn->name, efn->name_size, 1, ef->fp) != 1) + if (fwrite(efn->name, efn->name_size, 1, fp) != 1) goto write_error; } } /* write strings */ if (ef->ed) - { - for (j = 0; j < ef->ed->count; ++j) - { - if (ef->ed->all[j].str) - { - if (fwrite(ef->ed->all[j].str, ef->ed->all[j].len, 1, ef->fp) != 1) - goto write_error; - } - else - { - if (fwrite(ef->ed->all[j].mmap, ef->ed->all[j].len, 1, ef->fp) != 1) - goto write_error; - } - } - } + for (j = 0; j < ef->ed->count; ++j) + { + if (fwrite(ef->ed->all[j].str, ef->ed->all[j].len, 1, fp) != 1) + goto write_error; + } /* write data */ for (i = 0; i < num; i++) { for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) { - if (fwrite(efn->data, efn->size, 1, ef->fp) != 1) + if (fwrite(efn->data, efn->size, 1, fp) != 1) goto write_error; } } + /* flush all write to the file. */ + fflush(fp); + + /* append signature if required */ + if (ef->key) + { + error = eet_identity_sign(fp, ef->key); + if (error != EET_ERROR_NONE) + goto sign_error; + } + /* no more writes pending */ ef->writes_pending = 0; + fclose(fp); + return EET_ERROR_NONE; - write_error: - switch (ferror(ef->fp)) +write_error: + if (ferror(fp)) { - case EFBIG: error = EET_ERROR_WRITE_ERROR_FILE_TOO_BIG; break; - case EIO: error = EET_ERROR_WRITE_ERROR_IO_ERROR; break; - case ENOSPC: error = EET_ERROR_WRITE_ERROR_OUT_OF_SPACE; break; - case EPIPE: error = EET_ERROR_WRITE_ERROR_FILE_CLOSED; break; - default: error = EET_ERROR_WRITE_ERROR; break; + switch (errno) + { + case EFBIG: error = EET_ERROR_WRITE_ERROR_FILE_TOO_BIG; break; + + case EIO: error = EET_ERROR_WRITE_ERROR_IO_ERROR; break; + + case ENOSPC: error = EET_ERROR_WRITE_ERROR_OUT_OF_SPACE; break; + + case EPIPE: error = EET_ERROR_WRITE_ERROR_FILE_CLOSED; break; + + default: error = EET_ERROR_WRITE_ERROR; break; + } } - if (ef->fp) fclose(ef->fp); - ef->fp = NULL; + +sign_error: + fclose(fp); return error; } -#if 0 /* Unused */ -/* flush out writes to an eet file */ -static Eet_Error -eet_flush(Eet_File *ef) +EAPI int +eet_init(void) { - Eet_File_Node *efn; - int head[3]; - int count = 0; - int size = 0; - int offset = 0; - int i; - int num; + if (++eet_init_count != 1) + return eet_init_count; - /* check to see its' an eet file pointer */ - if (eet_check_pointer(ef)) - return EET_ERROR_BAD_OBJECT; - if (eet_check_header(ef)) - return EET_ERROR_EMPTY; - if ((ef->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE)) - return EET_ERROR_NOT_WRITABLE; - if (!ef->writes_pending) - return EET_ERROR_NONE; + if (!eina_init()) + return --eet_init_count; - /* calculate total size in bytes of directory block */ - num = (1 << ef->header->directory->size); - for (i = 0; i < num; i++) + _eet_log_dom_global = eina_log_domain_register("eet", EET_DEFAULT_LOG_COLOR); + if (_eet_log_dom_global < 0) { - for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) - { - size += 20 + strlen(efn->name) + 1; - count++; - } + EINA_LOG_ERR("Eet Can not create a general log domain."); + goto shutdown_eina; } - /* calculate offsets per entry */ - offset = 0; - for (i = 0; i < num; i++) + eina_lock_new(&eet_cache_lock); + + if (!eet_mempool_init()) { - for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) - { - efn->offset = 12 + size + offset; - offset += efn->size; - } + EINA_LOG_ERR("Eet: Eet_Node mempool creation failed"); + goto unregister_log_domain; } - /* go thru and write the header */ - head[0] = (int) htonl ((unsigned int) EET_MAGIC_FILE); - head[1] = (int) htonl ((unsigned int) count); - head[2] = (int) htonl ((unsigned int) size); - - fseek(ef->fp, 0, SEEK_SET); - if (fwrite(head, 12, 1, ef->fp) != 1) - goto write_error; + if (!eet_node_init()) + { + EINA_LOG_ERR("Eet: Eet_Node mempool creation failed"); + goto shutdown_mempool; + } - for (i = 0; i < num; i++) +#ifdef HAVE_GNUTLS + /* Before the library can be used, it must initialize itself if needed. */ + if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0) { - for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) - { - unsigned int ibuf[5]; - int name_size; + gcry_check_version(NULL); + /* Disable warning messages about problems with the secure memory subsystem. + This command should be run right after gcry_check_version. */ + if (gcry_control(GCRYCTL_DISABLE_SECMEM_WARN)) + goto shutdown_eet; /* This command is used to allocate a pool of secure memory and thus + enabling the use of secure memory. It also drops all extra privileges the + process has (i.e. if it is run as setuid (root)). If the argument nbytes + is 0, secure memory will be disabled. The minimum amount of secure memory + allocated is currently 16384 bytes; you may thus use a value of 1 to + request that default size. */ + + if (gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0)) + WRN( + "BIG FAT WARNING: I AM UNABLE TO REQUEST SECMEM, Cryptographic operation are at risk !"); + } - name_size = strlen(efn->name) + 1; +# ifdef EINA_HAVE_THREADS + if (gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread)) + WRN( + "YOU ARE USING PTHREADS, BUT I CANNOT INITIALIZE THREADSAFE GCRYPT OPERATIONS!"); - ibuf[0] = (int) htonl ((unsigned int) efn->offset); - ibuf[1] = (int) htonl ((unsigned int) efn->compression); - ibuf[2] = (int) htonl ((unsigned int) efn->size); - ibuf[3] = (int) htonl ((unsigned int) efn->data_size); - ibuf[4] = (int) htonl ((unsigned int) name_size); +# endif /* ifdef EINA_HAVE_THREADS */ + if (gnutls_global_init()) + goto shutdown_eet; +#endif /* ifdef HAVE_GNUTLS */ +#ifdef HAVE_OPENSSL + ERR_load_crypto_strings(); + OpenSSL_add_all_algorithms(); +#endif /* ifdef HAVE_OPENSSL */ - if (fwrite(ibuf, sizeof(ibuf), 1, ef->fp) != 1) - goto write_error; - if (fwrite(efn->name, name_size, 1, ef->fp) != 1) - goto write_error; - } - } + return eet_init_count; - /* write data */ - for (i = 0; i < num; i++) +#ifdef HAVE_GNUTLS +shutdown_eet: +#endif + eet_node_shutdown(); +shutdown_mempool: + eet_mempool_shutdown(); +unregister_log_domain: + eina_log_domain_unregister(_eet_log_dom_global); + _eet_log_dom_global = -1; +shutdown_eina: + eina_shutdown(); + return --eet_init_count; +} + +EAPI int +eet_shutdown(void) +{ + if (eet_init_count <= 0) { - for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) - { - if (fwrite(efn->data, efn->size, 1, ef->fp) != 1) - goto write_error; - } + ERR("Init count not greater than 0 in shutdown."); + return 0; } + if (--eet_init_count != 0) + return eet_init_count; - /* no more writes pending */ - ef->writes_pending = 0; + eet_clearcache(); - return EET_ERROR_NONE; + if (eet_writers_num || eet_readers_num) + { + Eet_File **closelist = NULL; + int num = 0; + int i; - write_error: - switch (ferror(ef->fp)) - { - case EFBIG: - fclose(ef->fp); - ef->fp = NULL; - return EET_ERROR_WRITE_ERROR_FILE_TOO_BIG; - case EIO: - fclose(ef->fp); - ef->fp = NULL; - return EET_ERROR_WRITE_ERROR_IO_ERROR; - case ENOSPC: - fclose(ef->fp); - ef->fp = NULL; - return EET_ERROR_WRITE_ERROR_OUT_OF_SPACE; - case EPIPE: - fclose(ef->fp); - ef->fp = NULL; - return EET_ERROR_WRITE_ERROR_FILE_CLOSED; - default: - fclose(ef->fp); - ef->fp = NULL; - return EET_ERROR_WRITE_ERROR; + closelist = alloca((eet_writers_num + eet_readers_num) + * sizeof(Eet_File *)); + for (i = 0; i < eet_writers_num; i++) + { + closelist[num++] = eet_writers[i]; + eet_writers[i]->delete_me_now = 1; + } + + for (i = 0; i < eet_readers_num; i++) + { + closelist[num++] = eet_readers[i]; + eet_readers[i]->delete_me_now = 1; + } + + for (i = 0; i < num; i++) + { + ERR("File '%s' is still open !", closelist[i]->path); + eet_internal_close(closelist[i], EINA_TRUE); + } } - fclose(ef->fp); - ef->fp = NULL; - return EET_ERROR_WRITE_ERROR; + eet_node_shutdown(); + eet_mempool_shutdown(); + + eina_lock_free(&eet_cache_lock); + +#ifdef HAVE_GNUTLS + /* Note that gnutls has a leak where it doesnt free stuff it alloced + * on init. valgrind trace here: + * 21 bytes in 1 blocks are definitely lost in loss record 24 of 194 + * at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) + * by 0x68AC801: strdup (strdup.c:43) + * by 0xD215B6A: p11_kit_registered_module_to_name (in /usr/lib/x86_64-linux-gnu/libp11-kit.so.0.0.0) + * by 0x9571574: gnutls_pkcs11_init (in /usr/lib/x86_64-linux-gnu/libgnutls.so.26.21.8) + * by 0x955B031: gnutls_global_init (in /usr/lib/x86_64-linux-gnu/libgnutls.so.26.21.8) + * by 0x6DFD6D0: eet_init (eet_lib.c:608) + * + * yes - i've tried calling gnutls_pkcs11_deinit() by hand but no luck. + * the leak is in there. + */ + gnutls_global_deinit(); +#endif /* ifdef HAVE_GNUTLS */ +#ifdef HAVE_OPENSSL + EVP_cleanup(); + ERR_free_strings(); +#endif /* ifdef HAVE_OPENSSL */ + eina_log_domain_unregister(_eet_log_dom_global); + _eet_log_dom_global = -1; + eina_shutdown(); + + return eet_init_count; } -#endif -EAPI int -eet_init(void) +EAPI Eet_Error +eet_sync(Eet_File *ef) { - return ++eet_initcount; -} + Eet_Error ret; -EAPI int -eet_shutdown(void) -{ - if (--eet_initcount == 0) - { - eet_clearcache(); - _eet_memfile_shutdown(); - } + if (eet_check_pointer(ef)) + return EET_ERROR_BAD_OBJECT; + + if ((ef->mode != EET_FILE_MODE_WRITE) && + (ef->mode != EET_FILE_MODE_READ_WRITE)) + return EET_ERROR_NOT_WRITABLE; + + if (!ef->writes_pending) + return EET_ERROR_NONE; + + LOCK_FILE(ef); - return eet_initcount; + ret = eet_flush2(ef); + + UNLOCK_FILE(ef); + return ret; } EAPI void eet_clearcache(void) { - int num = 0; - int i; + int num = 0; + int i; /* * We need to compute the list of eet file to close separately from the cache, * due to eet_close removing them from the cache after each call. */ + LOCK_CACHE; for (i = 0; i < eet_writers_num; i++) { - if (eet_writers[i]->references <= 0) num++; + if (eet_writers[i]->references <= 0) + num++; } for (i = 0; i < eet_readers_num; i++) { - if (eet_readers[i]->references <= 0) num++; + if (eet_readers[i]->references <= 0) + num++; } if (num > 0) { - Eet_File **closelist = NULL; - - closelist = alloca(num * sizeof(Eet_File *)); - num = 0; - for (i = 0; i < eet_writers_num; i++) - { - if (eet_writers[i]->references <= 0) - { - closelist[num] = eet_writers[i]; - eet_writers[i]->delete_me_now = 1; - num++; - } - } - - for (i = 0; i < eet_readers_num; i++) - { - if (eet_readers[i]->references <= 0) - { - closelist[num] = eet_readers[i]; - eet_readers[i]->delete_me_now = 1; - num++; - } - } - - for (i = 0; i < num; i++) - { - eet_close(closelist[i]); - } + Eet_File **closelist = NULL; + + closelist = alloca(num * sizeof(Eet_File *)); + num = 0; + for (i = 0; i < eet_writers_num; i++) + { + if (eet_writers[i]->references <= 0) + { + closelist[num] = eet_writers[i]; + eet_writers[i]->delete_me_now = 1; + num++; + } + } + + for (i = 0; i < eet_readers_num; i++) + { + if (eet_readers[i]->references <= 0) + { + closelist[num] = eet_readers[i]; + eet_readers[i]->delete_me_now = 1; + num++; + } + } + + for (i = 0; i < num; i++) + { + eet_internal_close(closelist[i], EINA_TRUE); + } } + + UNLOCK_CACHE; } /* FIXME: MMAP race condition in READ_WRITE_MODE */ static Eet_File * eet_internal_read2(Eet_File *ef) { - const int *data = (const int*) ef->data; - const char *start = (const char*) ef->data; - int index = 0; - int num_directory_entries; - int bytes_directory_entries; - int num_dictionary_entries; - int bytes_dictionary_entries; - int i; - - index += sizeof(int); - if (eet_test_close((int) ntohl(*data) != EET_MAGIC_FILE2, ef)) + const int *data = (const int *)ef->data; + const char *start = (const char *)ef->data; + int idx = 0; + unsigned long int bytes_directory_entries; + unsigned long int bytes_dictionary_entries; + unsigned long int signature_base_offset; + unsigned long int num_directory_entries; + unsigned long int num_dictionary_entries; + unsigned int i; + + idx += sizeof(int); + if (eet_test_close((int)ntohl(*data) != EET_MAGIC_FILE2, ef)) return NULL; + data++; -#define GET_INT(Value, Pointer, Index) \ - { \ - Value = ntohl(*Pointer); \ - Pointer++; \ - Index += sizeof(int); \ - } +#define GET_INT(Value, Pointer, Index) \ + { \ + Value = ntohl(*Pointer); \ + Pointer++; \ + Index += sizeof(int); \ + } /* get entries count and byte count */ - GET_INT(num_directory_entries, data, index); + GET_INT(num_directory_entries, data, idx); /* get dictionary count and byte count */ - GET_INT(num_dictionary_entries, data, index); + GET_INT(num_dictionary_entries, data, idx); - bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE; - bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries; + bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * + num_directory_entries + EET_FILE2_HEADER_SIZE; + bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * + num_dictionary_entries; - /* we cant have <= 0 values here - invalid */ - if (eet_test_close((num_directory_entries <= 0), ef)) + /* we can't have > 0x7fffffff values here - invalid */ + if (eet_test_close((num_directory_entries > 0x7fffffff), ef)) return NULL; - /* we cant have more bytes directory and bytes in dictionaries than the size of the file */ - if (eet_test_close((bytes_directory_entries + bytes_dictionary_entries) > ef->data_size, ef)) + /* we can't have more bytes directory and bytes in dictionaries than the size of the file */ + if (eet_test_close((bytes_directory_entries + bytes_dictionary_entries) > + ef->data_size, ef)) return NULL; /* allocate header */ - ef->header = calloc(1, sizeof(Eet_File_Header)); + ef->header = eet_file_header_calloc(1); if (eet_test_close(!ef->header, ef)) return NULL; ef->header->magic = EET_MAGIC_FILE_HEADER; /* allocate directory block in ram */ - ef->header->directory = calloc(1, sizeof(Eet_File_Directory)); + ef->header->directory = eet_file_directory_calloc(1); if (eet_test_close(!ef->header->directory, ef)) return NULL; /* 8 bit hash table (256 buckets) */ ef->header->directory->size = 8; /* allocate base hash table */ - ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size)); + ef->header->directory->nodes = + calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size)); if (eet_test_close(!ef->header->directory->nodes, ef)) return NULL; + signature_base_offset = 0; + if (num_directory_entries == 0) + { + signature_base_offset = ef->data_size; + } + /* actually read the directory block - all of it, into ram */ for (i = 0; i < num_directory_entries; ++i) { - const char *name; - Eet_File_Node *efn; - int name_offset; - int name_size; - int hash; - - /* out directory block is inconsistent - we have oveerun our */ + const char *name; + Eet_File_Node *efn; + unsigned long int name_offset; + unsigned long int name_size; + int hash; + int flag; + + /* out directory block is inconsistent - we have overrun our */ /* dynamic block buffer before we finished scanning dir entries */ - efn = malloc (sizeof(Eet_File_Node)); + efn = eet_file_node_malloc(1); if (eet_test_close(!efn, ef)) - return NULL; + { + if (efn) eet_file_node_mp_free(efn); /* yes i know - we only get here if + * efn is null/0 -> trying to shut up + * warning tools like cppcheck */ + return NULL; + } /* get entrie header */ - GET_INT(efn->offset, data, index); - GET_INT(efn->size, data, index); - GET_INT(efn->data_size, data, index); - GET_INT(name_offset, data, index); - GET_INT(name_size, data, index); - GET_INT(efn->compression, data, index); - -#define EFN_TEST(Test, Ef, Efn) \ - if (eet_test_close(Test, Ef)) \ - { \ - free(Efn); \ - return NULL; \ - } + GET_INT(efn->offset, data, idx); + GET_INT(efn->size, data, idx); + GET_INT(efn->data_size, data, idx); + GET_INT(name_offset, data, idx); + GET_INT(name_size, data, idx); + GET_INT(flag, data, idx); + + efn->compression = flag & 0x1 ? 1 : 0; + efn->ciphered = flag & 0x2 ? 1 : 0; + efn->alias = flag & 0x4 ? 1 : 0; + efn->compression_type = (flag >> 3) & 0xff; + +#define EFN_TEST(Test, Ef, Efn) \ + if (eet_test_close(Test, Ef)) \ + { \ + eet_file_node_mp_free(Efn); \ + return NULL; \ + } /* check data pointer position */ EFN_TEST(!((efn->size > 0) && (efn->offset + efn->size <= ef->data_size) - && (efn->offset > bytes_dictionary_entries + bytes_directory_entries)), ef, efn); + && (efn->offset > bytes_dictionary_entries + + bytes_directory_entries)), ef, efn); /* check name position */ EFN_TEST(!((name_size > 0) && (name_offset + name_size < ef->data_size) - && (name_offset >= bytes_dictionary_entries + bytes_directory_entries)), ef, efn); + && (name_offset >= bytes_dictionary_entries + + bytes_directory_entries)), ef, efn); name = start + name_offset; @@ -834,7 +913,7 @@ eet_internal_read2(Eet_File *ef) EFN_TEST(name[name_size - 1] != '\0', ef, efn); efn->free_name = 0; - efn->name = (char*) name; + efn->name = (char *)name; efn->name_size = name_size; hash = _eet_hash_gen(efn->name, ef->header->directory->size); @@ -843,73 +922,123 @@ eet_internal_read2(Eet_File *ef) /* read-only mode, so currently we have no data loaded */ if (ef->mode == EET_FILE_MODE_READ) - efn->data = NULL; - /* read-write mode - read everything into ram */ + efn->data = NULL; /* read-write mode - read everything into ram */ else { efn->data = malloc(efn->size); if (efn->data) memcpy(efn->data, ef->data + efn->offset, efn->size); } + + /* compute the possible position of a signature */ + if (signature_base_offset < efn->offset + efn->size) + signature_base_offset = efn->offset + efn->size; } ef->ed = NULL; if (num_dictionary_entries) { - const int *dico = (const int*) ef->data + EET_FILE2_DIRECTORY_ENTRY_COUNT * num_directory_entries + EET_FILE2_HEADER_COUNT; - int j; - - if (eet_test_close((num_directory_entries * EET_FILE2_DICTIONARY_ENTRY_SIZE + index) > (bytes_dictionary_entries + bytes_directory_entries), ef)) - return NULL; + const int *dico = (const int *)ef->data + + EET_FILE2_DIRECTORY_ENTRY_COUNT * num_directory_entries + + EET_FILE2_HEADER_COUNT; + int j; + + if (eet_test_close((num_dictionary_entries * + (int)EET_FILE2_DICTIONARY_ENTRY_SIZE + idx) > + (bytes_dictionary_entries + bytes_directory_entries), + ef)) + return NULL; - ef->ed = calloc(1, sizeof (Eet_Dictionary)); - if (eet_test_close(!ef->ed, ef)) return NULL; + ef->ed = eet_dictionary_add(); + if (eet_test_close(!ef->ed, ef)) + return NULL; - ef->ed->all = calloc(num_dictionary_entries, sizeof (Eet_String)); - if (eet_test_close(!ef->ed->all, ef)) return NULL; + ef->ed->all = calloc(1, num_dictionary_entries * sizeof(Eet_String)); + if (eet_test_close(!ef->ed->all, ef)) + return NULL; ef->ed->count = num_dictionary_entries; - ef->ed->total = num_dictionary_entries; - ef->ed->start = start + bytes_dictionary_entries + bytes_directory_entries; - ef->ed->end = ef->ed->start; + ef->ed->total = num_dictionary_entries; + ef->ed->start = start + bytes_dictionary_entries + + bytes_directory_entries; + ef->ed->end = ef->ed->start; for (j = 0; j < ef->ed->count; ++j) { - int hash; - int offset; + unsigned int offset; + int hash; - GET_INT(hash, dico, index); - GET_INT(offset, dico, index); - GET_INT(ef->ed->all[j].len, dico, index); - GET_INT(ef->ed->all[j].prev, dico, index); - GET_INT(ef->ed->all[j].next, dico, index); + GET_INT(hash, dico, idx); + GET_INT(offset, dico, idx); + GET_INT(ef->ed->all[j].len, dico, idx); + GET_INT(ef->ed->all[j].prev, dico, idx); + GET_INT(ef->ed->all[j].next, dico, idx); /* Hash value could be stored on 8bits data, but this will break alignment of all the others data. So stick to int and check the value. */ - if (eet_test_close(hash & 0xFFFFFF00, ef)) return NULL; + if (eet_test_close(hash & 0xFFFFFF00, ef)) + return NULL; /* Check string position */ if (eet_test_close(!((ef->ed->all[j].len > 0) - && (offset > (bytes_dictionary_entries + bytes_directory_entries)) - && (offset + ef->ed->all[j].len < ef->data_size)), ef)) + && (offset > + (bytes_dictionary_entries + + bytes_directory_entries)) + && (offset + ef->ed->all[j].len < + ef->data_size)), ef)) return NULL; - ef->ed->all[j].mmap = start + offset; - ef->ed->all[j].str = NULL; + ef->ed->all[j].str = start + offset; - if (ef->ed->all[j].mmap + ef->ed->all[j].len > ef->ed->end) - ef->ed->end = ef->ed->all[j].mmap + ef->ed->all[j].len; + if (ef->ed->all[j].str + ef->ed->all[j].len > ef->ed->end) + ef->ed->end = ef->ed->all[j].str + ef->ed->all[j].len; /* Check '\0' at the end of the string */ - if (eet_test_close(ef->ed->all[j].mmap[ef->ed->all[j].len - 1] != '\0', ef)) return NULL; + if (eet_test_close(ef->ed->all[j].str[ef->ed->all[j].len - 1] != + '\0', ef)) + return NULL; - ef->ed->all[j].hash = hash; + ef->ed->all[j].hash = hash; if (ef->ed->all[j].prev == -1) ef->ed->hash[hash] = j; + + /* compute the possible position of a signature */ + if (signature_base_offset < offset + ef->ed->all[j].len) + signature_base_offset = offset + ef->ed->all[j].len; } } + /* Check if the file is signed */ + ef->x509_der = NULL; + ef->x509_length = 0; + ef->signature = NULL; + ef->signature_length = 0; + + if (signature_base_offset < ef->data_size) + { +#ifdef HAVE_SIGNATURE + const unsigned char *buffer = ((const unsigned char *)ef->data) + + signature_base_offset; + ef->x509_der = eet_identity_check(ef->data, + signature_base_offset, + &ef->sha1, + &ef->sha1_length, + buffer, + ef->data_size - signature_base_offset, + &ef->signature, + &ef->signature_length, + &ef->x509_length); + + if (eet_test_close(!ef->x509_der, ef)) + return NULL; + +#else /* ifdef HAVE_SIGNATURE */ + ERR( + "This file could be signed but you didn't compile the necessary code to check the signature."); +#endif /* ifdef HAVE_SIGNATURE */ + } + return ef; } @@ -917,35 +1046,38 @@ eet_internal_read2(Eet_File *ef) static Eet_File * eet_internal_read1(Eet_File *ef) { - const unsigned char *dyn_buf = NULL; - const unsigned char *p = NULL; - int index = 0; - int num_entries; - int byte_entries; - int i; + const unsigned char *dyn_buf = NULL; + const unsigned char *p = NULL; + unsigned long int byte_entries; + unsigned long int num_entries; + unsigned int i; + int idx = 0; - fprintf(stderr, "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.\n", ef->path); + WRN( + "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.", + ef->path); /* build header table if read mode */ /* geat header */ - index += sizeof(int); + idx += sizeof(int); if (eet_test_close((int)ntohl(*((int *)ef->data)) != EET_MAGIC_FILE, ef)) return NULL; -#define EXTRACT_INT(Value, Pointer, Index) \ - { \ - int tmp; \ - memcpy(&tmp, Pointer + Index, sizeof(int)); \ - Value = ntohl(tmp); \ - Index += sizeof(int); \ - } +#define EXTRACT_INT(Value, Pointer, Index) \ + { \ + int tmp; \ + memcpy(&tmp, Pointer + Index, sizeof(int)); \ + Value = ntohl(tmp); \ + Index += sizeof(int); \ + } /* get entries count and byte count */ - EXTRACT_INT(num_entries, ef->data, index); - EXTRACT_INT(byte_entries, ef->data, index); + EXTRACT_INT(num_entries, ef->data, idx); + EXTRACT_INT(byte_entries, ef->data, idx); - /* we cant have <= 0 values here - invalid */ - if (eet_test_close((num_entries <= 0) || (byte_entries <= 0), ef)) + /* we can't have <= 0 values here - invalid */ + if (eet_test_close((num_entries > 0x7fffffff) || + (byte_entries > 0x7fffffff), ef)) return NULL; /* we can't have more entires than minimum bytes for those! invalid! */ @@ -953,431 +1085,597 @@ eet_internal_read1(Eet_File *ef) return NULL; /* check we will not outrun the file limit */ - if (eet_test_close(((byte_entries + sizeof(int) * 3) > ef->data_size), ef)) + if (eet_test_close(((byte_entries + (int)(sizeof(int) * 3)) > + ef->data_size), ef)) return NULL; /* allocate header */ - ef->header = calloc(1, sizeof(Eet_File_Header)); + ef->header = eet_file_header_calloc(1); if (eet_test_close(!ef->header, ef)) return NULL; ef->header->magic = EET_MAGIC_FILE_HEADER; /* allocate directory block in ram */ - ef->header->directory = calloc(1, sizeof(Eet_File_Directory)); + ef->header->directory = eet_file_directory_calloc(1); if (eet_test_close(!ef->header->directory, ef)) return NULL; /* 8 bit hash table (256 buckets) */ ef->header->directory->size = 8; /* allocate base hash table */ - ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size)); + ef->header->directory->nodes = + calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size)); if (eet_test_close(!ef->header->directory->nodes, ef)) return NULL; /* actually read the directory block - all of it, into ram */ - dyn_buf = ef->data + index; + dyn_buf = ef->data + idx; /* parse directory block */ p = dyn_buf; for (i = 0; i < num_entries; i++) { - Eet_File_Node *efn; - void *data = NULL; - int indexn = 0; - int name_size; - int hash; - int k; + Eet_File_Node *efn; + void *data = NULL; + int indexn = 0; + int name_size; + int hash; + int k; #define HEADER_SIZE (sizeof(int) * 5) - /* out directory block is inconsistent - we have oveerun our */ - /* dynamic block buffer before we finished scanning dir entries */ - if (eet_test_close(p + HEADER_SIZE >= (dyn_buf + byte_entries), ef)) - return NULL; + /* out directory block is inconsistent - we have overrun our */ + /* dynamic block buffer before we finished scanning dir entries */ + if (eet_test_close(p + HEADER_SIZE >= (dyn_buf + byte_entries), ef)) + return NULL; - /* allocate all the ram needed for this stored node accounting */ - efn = malloc (sizeof(Eet_File_Node)); - if (eet_test_close(!efn, ef)) - return NULL; + /* allocate all the ram needed for this stored node accounting */ + efn = eet_file_node_malloc(1); + if (eet_test_close(!efn, ef)) + { + if (efn) eet_file_node_mp_free(efn); /* yes i know - we only get here if + * efn is null/0 -> trying to shut up + * warning tools like cppcheck */ + return NULL; + } /* get entrie header */ - EXTRACT_INT(efn->offset, p, indexn); - EXTRACT_INT(efn->compression, p, indexn); - EXTRACT_INT(efn->size, p, indexn); - EXTRACT_INT(efn->data_size, p, indexn); - EXTRACT_INT(name_size, p, indexn); + EXTRACT_INT(efn->offset, p, indexn); + EXTRACT_INT(efn->compression, p, indexn); + EXTRACT_INT(efn->size, p, indexn); + EXTRACT_INT(efn->data_size, p, indexn); + EXTRACT_INT(name_size, p, indexn); efn->name_size = name_size; + efn->ciphered = 0; + efn->alias = 0; + + /* invalid size */ + if (eet_test_close(efn->size <= 0, ef)) + { + eet_file_node_mp_free(efn); + return NULL; + } + + /* invalid name_size */ + if (eet_test_close(name_size <= 0, ef)) + { + eet_file_node_mp_free(efn); + return NULL; + } + + /* reading name would mean falling off end of dyn_buf - invalid */ + if (eet_test_close((p + 16 + name_size) > (dyn_buf + byte_entries), ef)) + { + eet_file_node_mp_free(efn); + return NULL; + } + + /* This code is useless if we dont want backward compatibility */ + for (k = name_size; + k > 0 && ((unsigned char)*(p + HEADER_SIZE + k)) != 0; --k) + ; + + efn->free_name = ((unsigned char)*(p + HEADER_SIZE + k)) != 0; + + if (efn->free_name) + { + efn->name = malloc(sizeof(char) * name_size + 1); + if (eet_test_close(!efn->name, ef)) + { + eet_file_node_mp_free(efn); + return NULL; + } + + strncpy(efn->name, (char *)p + HEADER_SIZE, name_size); + efn->name[name_size] = 0; + + WRN( + "File: %s is not up to date for key \"%s\" - needs rebuilding sometime", + ef->path, + efn->name); + } + else + /* The only really useful peace of code for efn->name (no backward compatibility) */ + efn->name = (char *)((unsigned char *)(p + HEADER_SIZE)); + + /* get hash bucket it should go in */ + hash = _eet_hash_gen(efn->name, ef->header->directory->size); + efn->next = ef->header->directory->nodes[hash]; + ef->header->directory->nodes[hash] = efn; + + /* read-only mode, so currently we have no data loaded */ + if (ef->mode == EET_FILE_MODE_READ) + efn->data = NULL; /* read-write mode - read everything into ram */ + else + { + data = malloc(efn->size); + if (data) + memcpy(data, ef->data + efn->offset, efn->size); + + efn->data = data; + } - /* invalid size */ - if (eet_test_close(efn->size <= 0, ef)) - { - free (efn); - return NULL; - } - - /* invalid name_size */ - if (eet_test_close(name_size <= 0, ef)) - { - free (efn); - return NULL; - } - - /* reading name would mean falling off end of dyn_buf - invalid */ - if (eet_test_close((p + 16 + name_size) > (dyn_buf + byte_entries), ef)) - { - free (efn); - return NULL; - } - - /* This code is useless if we dont want backward compatibility */ - for (k = name_size; k > 0 && ((unsigned char) * (p + HEADER_SIZE + k)) != 0; --k) - ; - - efn->free_name = ((unsigned char) * (p + HEADER_SIZE + k)) != 0; - - if (efn->free_name) - { - efn->name = malloc(sizeof(char) * name_size + 1); - if (eet_test_close(efn->name == NULL, ef)) - { - free (efn); - return NULL; - } - - strncpy(efn->name, (char *)p + HEADER_SIZE, name_size); - efn->name[name_size] = 0; - - printf("File: %s is not up to date for key \"%s\" - needs rebuilding sometime\n", ef->path, efn->name); - } - else - /* The only really usefull peace of code for efn->name (no backward compatibility) */ - efn->name = (char*)((unsigned char*)(p + HEADER_SIZE)); - - /* get hash bucket it should go in */ - hash = _eet_hash_gen(efn->name, ef->header->directory->size); - efn->next = ef->header->directory->nodes[hash]; - ef->header->directory->nodes[hash] = efn; - - /* read-only mode, so currently we have no data loaded */ - if (ef->mode == EET_FILE_MODE_READ) - efn->data = NULL; - /* read-write mode - read everything into ram */ - else - { - data = malloc(efn->size); - if (data) - memcpy(data, ef->data + efn->offset, efn->size); - efn->data = data; - } - /* advance */ - p += HEADER_SIZE + name_size; + /* advance */ + p += HEADER_SIZE + name_size; } return ef; } -#endif +#endif /* if EET_OLD_EET_FILE_FORMAT */ + +/* + * this should only be called when the cache lock is already held + * (We could drop this restriction if we add a parameter to eet_test_close + * that indicates if the lock is held or not. For now it is easiest + * to just require that it is always held.) + */ static Eet_File * eet_internal_read(Eet_File *ef) { - const int *data = (const int*) ef->data; + const int *data = (const int *)ef->data; - if (eet_test_close((ef->data == (void *)-1) || (ef->data == NULL), ef)) + if (eet_test_close((ef->data == (void *)-1) || (!ef->data), ef)) return NULL; - if (eet_test_close(ef->data_size < sizeof(int) * 3, ef)) + if (eet_test_close(ef->data_size < (int)sizeof(int) * 3, ef)) return NULL; switch (ntohl(*data)) { #if EET_OLD_EET_FILE_FORMAT case EET_MAGIC_FILE: - return eet_internal_read1(ef); -#endif + return eet_internal_read1(ef); + +#endif /* if EET_OLD_EET_FILE_FORMAT */ case EET_MAGIC_FILE2: - return eet_internal_read2(ef); + return eet_internal_read2(ef); + default: - ef->delete_me_now = 1; - eet_close(ef); - break; + ef->delete_me_now = 1; + eet_internal_close(ef, EINA_TRUE); + break; } return NULL; } -#if 0 /* No prototype */ -EAPI Eet_File * -eet_memopen_read(const void *data, size_t size) +static Eet_Error +eet_internal_close(Eet_File *ef, + Eina_Bool locked) { - Eet_File *ef; - - if (data == NULL || size == 0) - return NULL; + Eet_Error err; - ef = malloc (sizeof (Eet_File)); - if (!ef) - return NULL; + /* check to see its' an eet file pointer */ + if (eet_check_pointer(ef)) + return EET_ERROR_BAD_OBJECT; - ef->ed = NULL; - ef->path = NULL; - ef->magic = EET_MAGIC_FILE; - ef->references = 1; - ef->mode = EET_FILE_MODE_READ; - ef->header = NULL; - ef->mtime = 0; - ef->delete_me_now = 1; - ef->fp = NULL; - ef->data = data; - ef->data_size = size; + if (!locked) + LOCK_CACHE; - return eet_internal_read(ef); -} -#endif + /* deref */ + ef->references--; + /* if its still referenced - dont go any further */ + if (ef->references > 0) + { + /* flush any writes */ + if ((ef->mode == EET_FILE_MODE_WRITE) || + (ef->mode == EET_FILE_MODE_READ_WRITE)) + eet_sync(ef); + goto on_error; + } + + err = eet_flush2(ef); + + eet_identity_unref(ef->key); + ef->key = NULL; + + /* if not urgent to delete it - dont free it - leave it in cache */ + if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ)) + goto on_error; + + /* remove from cache */ + if (ef->mode == EET_FILE_MODE_READ) + eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc); + else if ((ef->mode == EET_FILE_MODE_WRITE) || + (ef->mode == EET_FILE_MODE_READ_WRITE)) + eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc); + + /* we can unlock the cache now */ + if (!locked) + UNLOCK_CACHE; + + DESTROY_FILE(ef); + + /* free up data */ + if (ef->header) + { + if (ef->header->directory) + { + if (ef->header->directory->nodes) + { + int i, num; + + num = (1 << ef->header->directory->size); + for (i = 0; i < num; i++) + { + Eet_File_Node *efn; + + while ((efn = ef->header->directory->nodes[i])) + { + if (efn->data) + free(efn->data); + + ef->header->directory->nodes[i] = efn->next; + + if (efn->free_name) + free(efn->name); + + eet_file_node_mp_free(efn); + } + } + free(ef->header->directory->nodes); + } + + eet_file_directory_mp_free(ef->header->directory); + } + + eet_file_header_mp_free(ef->header); + } + + eet_dictionary_free(ef->ed); + + if (ef->sha1) + free(ef->sha1); + + if (ef->readfp) + { + if (ef->data) + eina_file_map_free(ef->readfp, (void *)ef->data); + + eina_file_close(ef->readfp); + } + + /* zero out ram for struct - caution tactic against stale memory use */ + memset(ef, 0, sizeof(Eet_File)); + + /* free it */ + eina_stringshare_del(ef->path); + eet_file_mp_free(ef); + return err; + +on_error: + if (!locked) + UNLOCK_CACHE; + + return EET_ERROR_NONE; +} EAPI Eet_File * -eet_open(const char *file, Eet_File_Mode mode) +eet_memopen_read(const void *data, + size_t size) { - FILE *fp; - Eet_File *ef; - int file_len; - struct stat file_stat; + Eet_File *ef; + + if (!data || size == 0) + return NULL; + + ef = eet_file_malloc(1); + if (!ef) + return NULL; + + INIT_FILE(ef); + ef->ed = NULL; + ef->path = NULL; + ef->key = NULL; + ef->magic = EET_MAGIC_FILE; + ef->references = 1; + ef->mode = EET_FILE_MODE_READ; + ef->header = NULL; + ef->delete_me_now = 1; + ef->readfp = NULL; + ef->data = data; + ef->data_size = size; + ef->sha1 = NULL; + ef->sha1_length = 0; + + /* eet_internal_read expects the cache lock to be held when it is called */ + LOCK_CACHE; + ef = eet_internal_read(ef); + UNLOCK_CACHE; + return ef; +} + +EAPI const char * +eet_file_get(Eet_File *ef) +{ + if (eet_check_pointer(ef)) return NULL; + return ef->path; +} + +EAPI Eet_File * +eet_open(const char *file, + Eet_File_Mode mode) +{ + Eina_File *fp; + Eet_File *ef; + int file_len; + unsigned long int size; if (!file) return NULL; /* find the current file handle in cache*/ ef = NULL; + LOCK_CACHE; if (mode == EET_FILE_MODE_READ) { - ef = eet_cache_find((char *)file, eet_writers, eet_writers_num); - if (ef) - { - eet_flush2(ef); - ef->references++; - ef->delete_me_now = 1; - eet_close(ef); - } - ef = eet_cache_find((char *)file, eet_readers, eet_readers_num); + ef = eet_cache_find((char *)file, eet_writers, eet_writers_num); + if (ef) + { + eet_sync(ef); + ef->references++; + ef->delete_me_now = 1; + eet_internal_close(ef, EINA_TRUE); + } + + ef = eet_cache_find((char *)file, eet_readers, eet_readers_num); } else if ((mode == EET_FILE_MODE_WRITE) || - (mode == EET_FILE_MODE_READ_WRITE)) + (mode == EET_FILE_MODE_READ_WRITE)) { - ef = eet_cache_find((char *)file, eet_readers, eet_readers_num); - if (ef) - { - ef->delete_me_now = 1; - ef->references++; - eet_close(ef); - } - ef = eet_cache_find((char *)file, eet_writers, eet_writers_num); + ef = eet_cache_find((char *)file, eet_readers, eet_readers_num); + if (ef) + { + ef->delete_me_now = 1; + ef->references++; + eet_internal_close(ef, EINA_TRUE); + } + + ef = eet_cache_find((char *)file, eet_writers, eet_writers_num); } - /* try open the file based on mode */ + /* try open the file based on mode */ if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE)) { - fp = fopen(file, "rb"); - if (!fp) goto on_error; - if (fstat(fileno(fp), &file_stat)) - { - fclose(fp); - fp = NULL; - goto on_error; - } - if ((mode == EET_FILE_MODE_READ) && - (file_stat.st_size < (sizeof(int) * 3))) - { - fclose(fp); - fp = NULL; - goto on_error; - } - - on_error: - if (fp == NULL && mode == EET_FILE_MODE_READ) return NULL; + /* Prevent garbage in futur comparison. */ + fp = eina_file_open(file, EINA_FALSE); + if (!fp) + { + size = 0; + goto open_error; + } + + size = eina_file_size_get(fp); + + if (size < ((int)sizeof(int) * 3)) + { + eina_file_close(fp); + fp = NULL; + + size = 0; + + goto open_error; + } + +open_error: + if (!fp && mode == EET_FILE_MODE_READ) + goto on_error; } else { - if (mode != EET_FILE_MODE_WRITE) return NULL; - memset(&file_stat, 0, sizeof(file_stat)); - /* opening for write - delete old copy of file right away */ - unlink(file); - fp = fopen(file, "wb"); + if (mode != EET_FILE_MODE_WRITE) + return NULL; + + size = 0; + + fp = NULL; } /* We found one */ - if (ef && (file_stat.st_mtime != ef->mtime)) + if (ef && ef->readfp != fp) { - ef->delete_me_now = 1; - ef->references++; - eet_close(ef); - ef = NULL; + ef->delete_me_now = 1; + ef->references++; + eet_internal_close(ef, EINA_TRUE); + ef = NULL; } if (ef) { - /* reference it up and return it */ - if (fp != NULL) fclose(fp); - ef->references++; - return ef; + /* reference it up and return it */ + if (fp) + eina_file_close(fp); + + ef->references++; + UNLOCK_CACHE; + return ef; } file_len = strlen(file) + 1; /* Allocate struct for eet file and have it zero'd out */ - ef = malloc(sizeof(Eet_File) + file_len); + ef = eet_file_malloc(1); if (!ef) - return NULL; + goto on_error; /* fill some of the members */ - ef->fp = fp; - ef->readfp = NULL; - ef->path = ((char *)ef) + sizeof(Eet_File); - memcpy(ef->path, file, file_len); + INIT_FILE(ef); + ef->key = NULL; + ef->readfp = fp; + ef->path = eina_stringshare_add_length(file, file_len); ef->magic = EET_MAGIC_FILE; ef->references = 1; ef->mode = mode; ef->header = NULL; - ef->mtime = file_stat.st_mtime; ef->writes_pending = 0; ef->delete_me_now = 0; ef->data = NULL; ef->data_size = 0; + ef->sha1 = NULL; + ef->sha1_length = 0; ef->ed = (mode == EET_FILE_MODE_WRITE) - || (ef->fp == NULL && mode == EET_FILE_MODE_READ_WRITE) ? + || (!ef->readfp && mode == EET_FILE_MODE_READ_WRITE) ? eet_dictionary_add() : NULL; - if (ef->fp == NULL && mode == EET_FILE_MODE_READ_WRITE) goto empty_file; + if (!ef->readfp && + (mode == EET_FILE_MODE_READ_WRITE || mode == EET_FILE_MODE_WRITE)) + goto empty_file; /* if we can't open - bail out */ - if (eet_test_close(!ef->fp, ef)) - return NULL; + if (eet_test_close(!ef->readfp, ef)) + goto on_error; - fcntl(fileno(ef->fp), F_SETFD, FD_CLOEXEC); /* if we opened for read or read-write */ if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE)) { - ef->data_size = file_stat.st_size; - ef->data = mmap(NULL, ef->data_size, PROT_READ, - MAP_SHARED, fileno(ef->fp), 0); - if (eet_test_close((ef->data == MAP_FAILED), ef)) - return NULL; - ef = eet_internal_read(ef); - if (!ef) - return NULL; - } - - empty_file: - /* we need to delete the original file in read-write mode and re-open for writing */ - if (ef->mode == EET_FILE_MODE_READ_WRITE) - { - ef->readfp = ef->fp; - ef->fp = NULL; + ef->data_size = size; + ef->data = eina_file_map_all(fp, EINA_FILE_SEQUENTIAL); + if (eet_test_close((ef->data == NULL), ef)) + goto on_error; + + ef = eet_internal_read(ef); + if (!ef) + goto on_error; } +empty_file: /* add to cache */ if (ef->references == 1) { - if (ef->mode == EET_FILE_MODE_READ) - eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc); - else - if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE)) - eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc); + if (ef->mode == EET_FILE_MODE_READ) + eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc); + else if ((ef->mode == EET_FILE_MODE_WRITE) || + (ef->mode == EET_FILE_MODE_READ_WRITE)) + eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc); } + UNLOCK_CACHE; return ef; + +on_error: + UNLOCK_CACHE; + return NULL; } EAPI Eet_File_Mode eet_mode_get(Eet_File *ef) { /* check to see its' an eet file pointer */ - if ((!ef) || (ef->magic != EET_MAGIC_FILE)) - return EET_FILE_MODE_INVALID; - else - return ef->mode; + if ((!ef) || (ef->magic != EET_MAGIC_FILE)) + return EET_FILE_MODE_INVALID; + else + return ef->mode; } -EAPI Eet_Error -eet_close(Eet_File *ef) +EAPI const void * +eet_identity_x509(Eet_File *ef, + int *der_length) { - Eet_Error err; + if (eet_check_pointer(ef)) + return NULL; - /* check to see its' an eet file pointer */ + if (!ef->x509_der) + return NULL; + + if (der_length) + *der_length = ef->x509_length; + + return ef->x509_der; +} + +EAPI const void * +eet_identity_signature(Eet_File *ef, + int *signature_length) +{ if (eet_check_pointer(ef)) - return EET_ERROR_BAD_OBJECT; - /* deref */ - ef->references--; - /* if its still referenced - dont go any further */ - if (ef->references > 0) return EET_ERROR_NONE; - /* flush any writes */ - err = eet_flush2(ef); + return NULL; - /* if not urgent to delete it - dont free it - leave it in cache */ - if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ)) - return EET_ERROR_NONE; + if (!ef->signature) + return NULL; - /* remove from cache */ - if (ef->mode == EET_FILE_MODE_READ) - eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc); - else if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE)) - eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc); + if (signature_length) + *signature_length = ef->signature_length; - /* free up data */ - if (ef->header) - { - if (ef->header->directory) - { - if (ef->header->directory->nodes) - { - int i, num; + return ef->signature; +} - num = (1 << ef->header->directory->size); - for (i = 0; i < num; i++) - { - Eet_File_Node *efn; +EAPI const void * +eet_identity_sha1(Eet_File *ef, + int *sha1_length) +{ + if (eet_check_pointer(ef)) + return NULL; - while ((efn = ef->header->directory->nodes[i])) - { - if (efn->data) - free(efn->data); + if (!ef->sha1) + ef->sha1 = eet_identity_compute_sha1(ef->data, + ef->data_size, + &ef->sha1_length); - ef->header->directory->nodes[i] = efn->next; + if (sha1_length) + *sha1_length = ef->sha1_length; - if (efn->free_name) - free(efn->name); + return ef->sha1; +} - free(efn); - } - } - free(ef->header->directory->nodes); - } - free(ef->header->directory); - } - free(ef->header); - } +EAPI Eet_Error +eet_identity_set(Eet_File *ef, + Eet_Key *key) +{ + Eet_Key *tmp; - eet_dictionary_free(ef->ed); + if (!ef) + return EET_ERROR_BAD_OBJECT; - if (ef->data) munmap((void*)ef->data, ef->data_size); - if (ef->fp) fclose(ef->fp); - if (ef->readfp) fclose(ef->readfp); + tmp = ef->key; + ef->key = key; + eet_identity_ref(ef->key); + eet_identity_unref(tmp); - /* zero out ram for struct - caution tactic against stale memory use */ - memset(ef, 0, sizeof(Eet_File)); + /* flags that writes are pending */ + ef->writes_pending = 1; - /* free it */ - free(ef); - return err; + return EET_ERROR_NONE; +} + +EAPI Eet_Error +eet_close(Eet_File *ef) +{ + return eet_internal_close(ef, EINA_FALSE); } EAPI void * -eet_read(Eet_File *ef, const char *name, int *size_ret) +eet_read_cipher(Eet_File *ef, + const char *name, + int *size_ret, + const char *cipher_key) { - void *data = NULL; - int size = 0; - Eet_File_Node *efn; + Eet_File_Node *efn; + char *data = NULL; + unsigned long int size = 0; if (size_ret) *size_ret = 0; @@ -1385,8 +1683,10 @@ eet_read(Eet_File *ef, const char *name, int *size_ret) /* check to see its' an eet file pointer */ if (eet_check_pointer(ef)) return NULL; + if (!name) return NULL; + if ((ef->mode != EET_FILE_MODE_READ) && (ef->mode != EET_FILE_MODE_READ_WRITE)) return NULL; @@ -1395,10 +1695,12 @@ eet_read(Eet_File *ef, const char *name, int *size_ret) if (eet_check_header(ef)) return NULL; + LOCK_FILE(ef); + /* hunt hash bucket */ efn = find_node_by_name(ef, name); if (!efn) - return NULL; + goto on_error; /* get size (uncompressed, if compressed at all) */ size = efn->data_size; @@ -1406,77 +1708,167 @@ eet_read(Eet_File *ef, const char *name, int *size_ret) /* allocate data */ data = malloc(size); if (!data) - return NULL; + goto on_error; /* uncompressed data */ if (efn->compression == 0) { - /* if we alreayd have the data in ram... copy that */ - if (efn->data) - memcpy(data, efn->data, efn->size); - else - if (!read_data_from_disk(ef, efn, data, size)) - { - free(data); - return NULL; - } + void *data_deciphered = NULL; + unsigned int data_deciphered_sz = 0; + /* if we already have the data in ram... copy that */ + + if (efn->ciphered && efn->size > size) + { + size = efn->size; + data = realloc(data, efn->size); + } + + if (efn->data) + memcpy(data, efn->data, size); + else + if (!read_data_from_disk(ef, efn, data, size)) + goto on_error; + + if (efn->ciphered && cipher_key) + { + if (eet_decipher(data, efn->size, cipher_key, strlen(cipher_key), + &data_deciphered, &data_deciphered_sz)) + { + if (data_deciphered) + free(data_deciphered); + + goto on_error; + } + + free(data); + data = data_deciphered; + size = data_deciphered_sz; + } } /* compressed data */ else { - void *tmp_data; - int free_tmp = 0; - int compr_size = efn->size; - uLongf dlen; - - /* if we already have the data in ram... copy that */ - if (efn->data) - tmp_data = efn->data; - else - { - tmp_data = malloc(compr_size); - if (!tmp_data) - { - free(data); - return NULL; - } - - free_tmp = 1; - - if (!read_data_from_disk(ef, efn, tmp_data, compr_size)) - { - free(tmp_data); - free(data); - return NULL; - } - } - - /* decompress it */ - dlen = size; - if (uncompress((Bytef *)data, &dlen, - tmp_data, (uLongf)compr_size)) - { - free(data); - return NULL; - } - - if (free_tmp) - free(tmp_data); + void *tmp_data = NULL; + void *data_deciphered = NULL; + unsigned int data_deciphered_sz = 0; + int free_tmp = 0, ret; + int compr_size = efn->size; + uLongf dlen; + + /* if we already have the data in ram... copy that */ + if (efn->data) + tmp_data = efn->data; + else + { + tmp_data = malloc(compr_size); + if (!tmp_data) + goto on_error; + + free_tmp = 1; + + if (!read_data_from_disk(ef, efn, tmp_data, compr_size)) + { + free(tmp_data); + goto on_error; + } + } + + if (efn->ciphered && cipher_key) + { + if (eet_decipher(tmp_data, compr_size, cipher_key, + strlen(cipher_key), &data_deciphered, + &data_deciphered_sz)) + { + if (free_tmp) + free(tmp_data); + + if (data_deciphered) + free(data_deciphered); + + goto on_error; + } + + if (free_tmp) + free(tmp_data); + free_tmp = 1; + tmp_data = data_deciphered; + compr_size = data_deciphered_sz; + } + + /* decompress it */ + dlen = size; + switch (efn->compression_type) + { + case EET_COMPRESSION_VERYFAST: + case EET_COMPRESSION_SUPERFAST: + ret = LZ4_uncompress(tmp_data, data, dlen); + if (ret != compr_size) + { + if (free_tmp) + free(tmp_data); + goto on_error; + } + break; + default: + if (uncompress((Bytef *)data, &dlen, + tmp_data, (uLongf)compr_size) != Z_OK) + { + if (free_tmp) + free(tmp_data); + goto on_error; + } + break; + } + + if (free_tmp) + free(tmp_data); } + UNLOCK_FILE(ef); + + /* handle alias */ + if (efn->alias) + { + void *tmp; + + if (data[size - 1] != '\0') + goto on_error; + + tmp = eet_read_cipher(ef, data, size_ret, cipher_key); + + free(data); + + data = tmp; + } + else /* fill in return values */ if (size_ret) *size_ret = size; return data; + +on_error: + UNLOCK_FILE(ef); + free(data); + return NULL; +} + +EAPI void * +eet_read(Eet_File *ef, + const char *name, + int *size_ret) +{ + return eet_read_cipher(ef, name, size_ret, NULL); } EAPI const void * -eet_read_direct(Eet_File *ef, const char *name, int *size_ret) +eet_read_direct(Eet_File *ef, + const char *name, + int *size_ret) { - const void *data = NULL; - int size = 0; Eet_File_Node *efn; + const char *data = NULL; + int size = 0, ret; if (size_ret) *size_ret = 0; @@ -1484,8 +1876,10 @@ eet_read_direct(Eet_File *ef, const char *name, int *size_ret) /* check to see its' an eet file pointer */ if (eet_check_pointer(ef)) return NULL; + if (!name) return NULL; + if ((ef->mode != EET_FILE_MODE_READ) && (ef->mode != EET_FILE_MODE_READ_WRITE)) return NULL; @@ -1494,21 +1888,83 @@ eet_read_direct(Eet_File *ef, const char *name, int *size_ret) if (eet_check_header(ef)) return NULL; + LOCK_FILE(ef); + /* hunt hash bucket */ efn = find_node_by_name(ef, name); if (!efn) - return NULL; + goto on_error; - if (efn->offset < 0 && efn->data == NULL) - return NULL; + /* trick to detect data in memory instead of mmaped from disk */ + if (efn->offset > ef->data_size && !efn->data) + goto on_error; /* get size (uncompressed, if compressed at all) */ size = efn->data_size; + if (efn->alias) + { + data = efn->data ? efn->data : ef->data + efn->offset; + + /* handle alias case */ + if (efn->compression) + { + const void *retptr; + char *tmp; + int compr_size = efn->size; + uLongf dlen; + + tmp = malloc(compr_size); + if (!tmp) goto on_error; + switch (efn->compression_type) + { + case EET_COMPRESSION_VERYFAST: + case EET_COMPRESSION_SUPERFAST: + ret = LZ4_uncompress(data, tmp, size); + if (ret != compr_size) + { + free(tmp); + goto on_error; + } + break; + default: + dlen = size; + + if (uncompress((Bytef *)tmp, &dlen, (Bytef *)data, + (uLongf)compr_size)) + { + free(tmp); + goto on_error; + } + } + + if (tmp[compr_size - 1] != '\0') + { + free(tmp); + goto on_error; + } + + UNLOCK_FILE(ef); + + retptr = eet_read_direct(ef, tmp, size_ret); + free(tmp); + return retptr; + } + + if (!data) + goto on_error; + + if (data[size - 1] != '\0') + goto on_error; + + UNLOCK_FILE(ef); + + return eet_read_direct(ef, data, size_ret); + } + else /* uncompressed data */ - if (efn->compression == 0) - data = efn->data ? efn->data : ef->data + efn->offset; - /* compressed data */ + if ((efn->compression == 0) && (efn->ciphered == 0)) + data = efn->data ? efn->data : ef->data + efn->offset; /* compressed data */ else data = NULL; @@ -1516,142 +1972,540 @@ eet_read_direct(Eet_File *ef, const char *name, int *size_ret) if (size_ret) *size_ret = size; + UNLOCK_FILE(ef); + return data; + +on_error: + UNLOCK_FILE(ef); + return NULL; +} + +EAPI const char * +eet_alias_get(Eet_File *ef, + const char *name) +{ + Eet_File_Node *efn; + const char *data = NULL; + int size = 0, ret; + + /* check to see its' an eet file pointer */ + if (eet_check_pointer(ef)) + return NULL; + + if (!name) + return NULL; + + if ((ef->mode != EET_FILE_MODE_READ) && + (ef->mode != EET_FILE_MODE_READ_WRITE)) + return NULL; + + /* no header, return NULL */ + if (eet_check_header(ef)) + return NULL; + + LOCK_FILE(ef); + + /* hunt hash bucket */ + efn = find_node_by_name(ef, name); + if (!efn) + goto on_error; + + /* trick to detect data in memory instead of mmaped from disk */ + if (efn->offset > ef->data_size && !efn->data) + goto on_error; + + /* get size (uncompressed, if compressed at all) */ + size = efn->data_size; + + if (!efn->alias) return NULL; + data = efn->data ? efn->data : ef->data + efn->offset; + + /* handle alias case */ + if (efn->compression) + { + const char *retptr; + char *tmp; + int compr_size = efn->size; + uLongf dlen; + + tmp = malloc(compr_size); + if (!tmp) goto on_error; + switch (efn->compression_type) + { + case EET_COMPRESSION_VERYFAST: + case EET_COMPRESSION_SUPERFAST: + ret = LZ4_uncompress(data, tmp, size); + if (ret != compr_size) + { + free(tmp); + goto on_error; + } + break; + default: + dlen = size; + + if (uncompress((Bytef *)tmp, &dlen, (Bytef *)data, + (uLongf)compr_size)) + { + free(tmp); + goto on_error; + } + } + + if (tmp[compr_size - 1] != '\0') + goto on_error; + + UNLOCK_FILE(ef); + + retptr = eina_stringshare_add(tmp); + free(tmp); + return retptr; + } + + if (!data) + goto on_error; + + if (data[size - 1] != '\0') + goto on_error; + + UNLOCK_FILE(ef); + + return eina_stringshare_add(data); + +on_error: + UNLOCK_FILE(ef); + return NULL; +} + +EAPI Eina_Bool +eet_alias(Eet_File *ef, + const char *name, + const char *destination, + int comp) +{ + Eet_File_Node *efn; + void *data2; + Eina_Bool exists_already = EINA_FALSE; + int data_size, ret, hash, slen; + + /* check to see its' an eet file pointer */ + if (eet_check_pointer(ef)) + return EINA_FALSE; + + if ((!name) || (!destination)) + return EINA_FALSE; + + if ((ef->mode != EET_FILE_MODE_WRITE) && + (ef->mode != EET_FILE_MODE_READ_WRITE)) + return EINA_FALSE; + + LOCK_FILE(ef); + + if (!ef->header) + { + /* allocate header */ + ef->header = eet_file_header_calloc(1); + if (!ef->header) + goto on_error; + + ef->header->magic = EET_MAGIC_FILE_HEADER; + /* allocate directory block in ram */ + ef->header->directory = eet_file_directory_calloc(1); + if (!ef->header->directory) + { + eet_file_header_mp_free(ef->header); + ef->header = NULL; + goto on_error; + } + + /* 8 bit hash table (256 buckets) */ + ef->header->directory->size = 8; + /* allocate base hash table */ + ef->header->directory->nodes = + calloc(1, sizeof(Eet_File_Node *) * + (1 << ef->header->directory->size)); + if (!ef->header->directory->nodes) + { + eet_file_directory_mp_free(ef->header->directory); + ef->header = NULL; + goto on_error; + } + } + + /* figure hash bucket */ + hash = _eet_hash_gen(name, ef->header->directory->size); + + slen = strlen(destination) + 1; + data_size = comp ? + 12 + ((slen * 101) / 100) + : slen; + if (comp) + { + ret = LZ4_compressBound(slen); + if ((ret > 0) && (ret > data_size)) data_size = ret; + } + + data2 = malloc(data_size); + if (!data2) goto on_error; + + /* if we want to compress */ + if (comp) + { + switch (comp) + { + case EET_COMPRESSION_VERYFAST: + ret = LZ4_compressHC((const char *)destination, (char *)data2, + slen); + if (ret <= 0) + { + free(data2); + goto on_error; + } + data_size = ret; + break; + case EET_COMPRESSION_SUPERFAST: + ret = LZ4_compress((const char *)destination, (char *)data2, + slen); + if (ret <= 0) + { + free(data2); + goto on_error; + } + data_size = ret; + break; + default: + { + uLongf buflen; + + /* compress the data with max compression */ + buflen = (uLongf)data_size; + if (compress2((Bytef *)data2, &buflen, + (const Bytef *)destination, + (uLong)slen, Z_BEST_COMPRESSION) != Z_OK) + { + free(data2); + goto on_error; + } + /* record compressed chunk size */ + data_size = (int)buflen; + } + break; + } + if ((data_size < 0) || + (data_size >= (int)(strlen(destination) + 1))) + { + comp = 0; + data_size = strlen(destination) + 1; + } + else + { + void *data3; + + data3 = realloc(data2, data_size); + if (data3) data2 = data3; + } + } + + if (!comp) memcpy(data2, destination, data_size); + + /* Does this node already exist? */ + for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next) + { + /* if it matches */ + if ((efn->name) && (eet_string_match(efn->name, name))) + { + free(efn->data); + efn->alias = 1; + efn->ciphered = 0; + efn->compression = !!comp; + efn->compression_type = comp; + efn->size = data_size; + efn->data_size = strlen(destination) + 1; + efn->data = data2; + /* Put the offset above the limit to avoid direct access */ + efn->offset = ef->data_size + 1; + exists_already = EINA_TRUE; + break; + } + } + if (!exists_already) + { + efn = eet_file_node_malloc(1); + if (!efn) + { + free(data2); + goto on_error; + } + + efn->name = strdup(name); + efn->name_size = strlen(efn->name) + 1; + efn->free_name = 1; + + efn->next = ef->header->directory->nodes[hash]; + ef->header->directory->nodes[hash] = efn; + /* Put the offset above the limit to avoid direct access */ + efn->offset = ef->data_size + 1; + efn->alias = 1; + efn->ciphered = 0; + efn->compression = !!comp; + efn->compression_type = comp; + efn->size = data_size; + efn->data_size = strlen(destination) + 1; + efn->data = data2; + } + + /* flags that writes are pending */ + ef->writes_pending = 1; + + UNLOCK_FILE(ef); + return EINA_TRUE; + +on_error: + UNLOCK_FILE(ef); + return EINA_FALSE; } EAPI int -eet_write(Eet_File *ef, const char *name, const void *data, int size, int compress) +eet_write_cipher(Eet_File *ef, + const char *name, + const void *data, + int size, + int comp, + const char *cipher_key) { - Eet_File_Node *efn; - void *data2; - int exists_already = 0; - int data_size; - int hash; + Eet_File_Node *efn; + void *data2 = NULL; + int exists_already = 0, data_size, hash, ret; /* check to see its' an eet file pointer */ if (eet_check_pointer(ef)) return 0; + if ((!name) || (!data) || (size <= 0)) return 0; + if ((ef->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE)) return 0; + LOCK_FILE(ef); + if (!ef->header) { - /* allocate header */ - ef->header = calloc(1, sizeof(Eet_File_Header)); - if (!ef->header) - return 0; - - ef->header->magic = EET_MAGIC_FILE_HEADER; - /* allocate directory block in ram */ - ef->header->directory = calloc(1, sizeof(Eet_File_Directory)); - if (!ef->header->directory) - return 0; - - /* 8 bit hash table (256 buckets) */ - ef->header->directory->size = 8; - /* allocate base hash table */ - ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size)); - if (!ef->header->directory->nodes) - return 0; + /* allocate header */ + ef->header = eet_file_header_calloc(1); + if (!ef->header) + goto on_error; + + ef->header->magic = EET_MAGIC_FILE_HEADER; + /* allocate directory block in ram */ + ef->header->directory = eet_file_directory_calloc(1); + if (!ef->header->directory) + { + eet_file_header_mp_free(ef->header); + ef->header = NULL; + goto on_error; + } + + /* 8 bit hash table (256 buckets) */ + ef->header->directory->size = 8; + /* allocate base hash table */ + ef->header->directory->nodes = + calloc(1, sizeof(Eet_File_Node *) * + (1 << ef->header->directory->size)); + if (!ef->header->directory->nodes) + { + eet_file_directory_mp_free(ef->header->directory); + ef->header = NULL; + goto on_error; + } } /* figure hash bucket */ hash = _eet_hash_gen(name, ef->header->directory->size); - data_size = compress ? 12 + ((size * 101) / 100) : size; - - data2 = malloc(data_size); - if (!data2) - return 0; + UNLOCK_FILE(ef); + + data_size = comp ? 12 + ((size * 101) / 100) : size; + if (comp) + { + ret = LZ4_compressBound(size); + if ((ret > 0) && (ret > data_size)) data_size = ret; + } + + if (comp || !cipher_key) + { + data2 = malloc(data_size); + if (!data2) + goto on_error; + } /* if we want to compress */ - if (compress) - { - uLongf buflen; - - /* compress the data with max compression */ - buflen = (uLongf)data_size; - if (compress2((Bytef *)data2, &buflen, (Bytef *)data, - (uLong)size, Z_BEST_COMPRESSION) != Z_OK) - { - free(data2); - return 0; - } - /* record compressed chunk size */ - data_size = (int)buflen; - if (data_size < 0 || data_size >= size) - { - compress = 0; - data_size = size; - } - else - { - void *data3; - - data3 = realloc(data2, data_size); - if (data3) - data2 = data3; - } - } - if (!compress) + if (comp) + { + switch (comp) + { + case EET_COMPRESSION_VERYFAST: + ret = LZ4_compressHC((const char *)data, (char *)data2, size); + if (ret <= 0) + { + free(data2); + LOCK_FILE(ef); + goto on_error; + } + data_size = ret; + break; + case EET_COMPRESSION_SUPERFAST: + ret = LZ4_compress((const char *)data, (char *)data2, size); + if (ret <= 0) + { + free(data2); + LOCK_FILE(ef); + goto on_error; + } + data_size = ret; + break; + default: + { + uLongf buflen; + + /* compress the data with max compression */ + buflen = (uLongf)data_size; + if (compress2((Bytef *)data2, &buflen, (Bytef *)data, + (uLong)size, Z_BEST_COMPRESSION) != Z_OK) + { + free(data2); + LOCK_FILE(ef); + goto on_error; + } + /* record compressed chunk size */ + data_size = (int)buflen; + } + } + if ((data_size < 0) || (data_size >= size)) + { + comp = 0; + data_size = size; + } + else + { + void *data3; + + data3 = realloc(data2, data_size); + if (data3) + data2 = data3; + } + } + + if (cipher_key) + { + void *data_ciphered = NULL; + unsigned int data_ciphered_sz = 0; + const void *tmp; + + tmp = comp ? data2 : data; + if (!eet_cipher(tmp, data_size, cipher_key, strlen(cipher_key), + &data_ciphered, &data_ciphered_sz)) + { + if (data2) + free(data2); + + data2 = data_ciphered; + data_size = data_ciphered_sz; + } + else + { + if (data_ciphered) + free(data_ciphered); + + cipher_key = NULL; + } + } + else + if (!comp) memcpy(data2, data, size); + LOCK_FILE(ef); /* Does this node already exist? */ for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next) { - /* if it matches */ - if ((efn->name) && (eet_string_match(efn->name, name))) - { - free(efn->data); - efn->compression = !!compress; - efn->size = data_size; - efn->data_size = size; - efn->data = data2; - efn->offset = -1; - exists_already = 1; - break; - } + /* if it matches */ + if ((efn->name) && (eet_string_match(efn->name, name))) + { + free(efn->data); + efn->alias = 0; + efn->ciphered = cipher_key ? 1 : 0; + efn->compression = !!comp; + efn->compression_type = comp; + efn->size = data_size; + efn->data_size = size; + efn->data = data2; + /* Put the offset above the limit to avoid direct access */ + efn->offset = ef->data_size + 1; + exists_already = 1; + break; + } } if (!exists_already) { - efn = malloc(sizeof(Eet_File_Node)); - if (!efn) - { - free(data2); - return 0; - } - efn->name = strdup(name); + efn = eet_file_node_malloc(1); + if (!efn) + { + free(data2); + goto on_error; + } + + efn->name = strdup(name); efn->name_size = strlen(efn->name) + 1; efn->free_name = 1; - efn->next = ef->header->directory->nodes[hash]; - ef->header->directory->nodes[hash] = efn; - efn->offset = -1; - efn->compression = !!compress; - efn->size = data_size; - efn->data_size = size; - efn->data = data2; + efn->next = ef->header->directory->nodes[hash]; + ef->header->directory->nodes[hash] = efn; + /* Put the offset above the limit to avoid direct access */ + efn->offset = ef->data_size + 1; + efn->alias = 0; + efn->ciphered = cipher_key ? 1 : 0; + efn->compression = !!comp; + efn->compression_type = comp; + efn->size = data_size; + efn->data_size = size; + efn->data = data2; } /* flags that writes are pending */ ef->writes_pending = 1; + UNLOCK_FILE(ef); return data_size; + +on_error: + UNLOCK_FILE(ef); + return 0; } EAPI int -eet_delete(Eet_File *ef, const char *name) +eet_write(Eet_File *ef, + const char *name, + const void *data, + int size, + int comp) { - Eet_File_Node *efn; - Eet_File_Node *pefn; - int hash; - int exists_already = 0; + return eet_write_cipher(ef, name, data, size, comp, NULL); +} + +EAPI int +eet_delete(Eet_File *ef, + const char *name) +{ + Eet_File_Node *efn; + Eet_File_Node *pefn; + int hash; + int exists_already = 0; /* check to see its' an eet file pointer */ if (eet_check_pointer(ef)) return 0; + if (!name) return 0; @@ -1662,35 +2516,41 @@ eet_delete(Eet_File *ef, const char *name) if (eet_check_header(ef)) return 0; + LOCK_FILE(ef); + /* figure hash bucket */ hash = _eet_hash_gen(name, ef->header->directory->size); /* Does this node already exist? */ for (pefn = NULL, efn = ef->header->directory->nodes[hash]; - efn; - pefn = efn, efn = efn->next) - { - /* if it matches */ - if (eet_string_match(efn->name, name)) - { - if (efn->data) - free(efn->data); - - if (efn == ef->header->directory->nodes[hash]) - ef->header->directory->nodes[hash] = efn->next; - else - pefn->next = efn->next; - - if (efn->free_name) free(efn->name); - free(efn); - exists_already = 1; - break; - } + efn; + pefn = efn, efn = efn->next) + { + /* if it matches */ + if (eet_string_match(efn->name, name)) + { + if (efn->data) + free(efn->data); + + if (!pefn) + ef->header->directory->nodes[hash] = efn->next; + else + pefn->next = efn->next; + + if (efn->free_name) + free(efn->name); + + eet_file_node_mp_free(efn); + exists_already = 1; + break; + } } /* flags that writes are pending */ if (exists_already) ef->writes_pending = 1; + UNLOCK_FILE(ef); + /* update access time */ return exists_already; } @@ -1698,20 +2558,22 @@ eet_delete(Eet_File *ef, const char *name) EAPI Eet_Dictionary * eet_dictionary_get(Eet_File *ef) { - if (eet_check_pointer(ef)) return NULL; + if (eet_check_pointer(ef)) + return NULL; return ef->ed; } - EAPI char ** -eet_list(Eet_File *ef, const char *glob, int *count_ret) +eet_list(Eet_File *ef, + const char *glob, + int *count_ret) { - Eet_File_Node *efn; - char **list_ret = NULL; - int list_count = 0; - int list_count_alloc = 0; - int i, num; + Eet_File_Node *efn; + char **list_ret = NULL; + int list_count = 0; + int list_count_alloc = 0; + int i, num; /* check to see its' an eet file pointer */ if (eet_check_pointer(ef) || eet_check_header(ef) || @@ -1719,57 +2581,71 @@ eet_list(Eet_File *ef, const char *glob, int *count_ret) ((ef->mode != EET_FILE_MODE_READ) && (ef->mode != EET_FILE_MODE_READ_WRITE))) { - if (count_ret) - *count_ret = 0; + if (count_ret) + *count_ret = 0; - return NULL; + return NULL; } + if (!strcmp(glob, "*")) + glob = NULL; + + LOCK_FILE(ef); + /* loop through all entries */ num = (1 << ef->header->directory->size); for (i = 0; i < num; i++) { - for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) - { - /* if the entry matches the input glob - * check for * explicitly, because on some systems, * isn't well - * supported - */ - if ((!strcmp (glob, "*")) || !fnmatch(glob, efn->name, 0)) - { - /* add it to our list */ - list_count++; - - /* only realloc in 32 entry chunks */ - if (list_count > list_count_alloc) - { - char **new_list = NULL; - - list_count_alloc += 64; - new_list = realloc(list_ret, list_count_alloc * (sizeof(char *))); - if (!new_list) - { - free(list_ret); - - if (count_ret) - *count_ret = 0; - - return NULL; - } - list_ret = new_list; - } - - /* put pointer of name string in */ - list_ret[list_count - 1] = efn->name; - } - } + for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) + { + /* if the entry matches the input glob + * check for * explicitly, because on some systems, * isn't well + * supported + */ + if ((!glob) || !fnmatch(glob, efn->name, 0)) + { + /* add it to our list */ + list_count++; + + /* only realloc in 32 entry chunks */ + if (list_count > list_count_alloc) + { + char **new_list = NULL; + + list_count_alloc += 64; + new_list = + realloc(list_ret, list_count_alloc * (sizeof(char *))); + if (!new_list) + { + free(list_ret); + + goto on_error; + } + + list_ret = new_list; + } + + /* put pointer of name string in */ + list_ret[list_count - 1] = efn->name; + } + } } + UNLOCK_FILE(ef); + /* return count and list */ if (count_ret) *count_ret = list_count; return list_ret; + +on_error: + UNLOCK_FILE(ef); + + if (count_ret) + *count_ret = 0; + + return NULL; } EAPI int @@ -1784,19 +2660,24 @@ eet_num_entries(Eet_File *ef) (ef->mode != EET_FILE_MODE_READ_WRITE))) return -1; + LOCK_FILE(ef); + /* loop through all entries */ num = (1 << ef->header->directory->size); for (i = 0; i < num; i++) { - for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) - ret++; + for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) + ret++; } + UNLOCK_FILE(ef); + return ret; } static Eet_File_Node * -find_node_by_name(Eet_File *ef, const char *name) +find_node_by_name(Eet_File *ef, + const char *name) { Eet_File_Node *efn; int hash; @@ -1806,31 +2687,30 @@ find_node_by_name(Eet_File *ef, const char *name) for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next) { - if (eet_string_match(efn->name, name)) - return efn; + if (eet_string_match(efn->name, name)) + return efn; } return NULL; } static int -read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len) +read_data_from_disk(Eet_File *ef, + Eet_File_Node *efn, + void *buf, + int len) { - if (efn->offset < 0) return 0; + if (efn->offset > ef->data_size) + return 0; - if (ef->data) - { - if ((efn->offset + len) > ef->data_size) return 0; - memcpy(buf, ef->data + efn->offset, len); - } - else - { - /* seek to data location */ - if (fseek(ef->fp, efn->offset, SEEK_SET) < 0) - return 0; + if (!ef->data) + return 0; + + if ((efn->offset + len) > ef->data_size) + return 0; + + memcpy(buf, ef->data + efn->offset, len); - /* read it */ - len = fread(buf, len, 1, ef->fp); - } return len; } + diff --git a/src/lib/eet_node.c b/src/lib/eet_node.c new file mode 100644 index 0000000..faaa905 --- /dev/null +++ b/src/lib/eet_node.c @@ -0,0 +1,797 @@ +#ifdef HAVE_CONFIG_H +# include +#endif /* ifdef HAVE_CONFIG_H */ + +#include +#include + +#ifdef HAVE_EVIL +# include +#endif /* ifdef HAVE_EVIL */ + +#include + +#include "Eet.h" +#include "Eet_private.h" + +static Eina_Mempool *_eet_node_mp = NULL; + +Eet_Node * +eet_node_new(void) +{ + Eet_Node *result; + + result = eina_mempool_malloc(_eet_node_mp, sizeof (Eet_Node)); + if (!result) + return NULL; + + memset(result, 0, sizeof (Eet_Node)); + return result; +} + +void +eet_node_free(Eet_Node *node) +{ + eina_mempool_free(_eet_node_mp, node); +} + +static Eet_Node * +_eet_node_new(const char *name, + int type) +{ + Eet_Node *n; + + n = eet_node_new(); + if (!n) + return NULL; + + n->type = type; + n->name = eina_stringshare_add(name); + + return n; +} + +static void +_eet_node_append(Eet_Node *n, + Eina_List *nodes) +{ + Eet_Node *value; + Eina_List *l; + + EINA_LIST_REVERSE_FOREACH(nodes, l, value) + { + value->next = n->values; + n->values = value; + } +} + +#define EET_NODE_NEW(Eet_type, Name, Value, Type) \ + EAPI Eet_Node * \ + eet_node_ ## Name ## _new(const char *name, Type Value) \ + { \ + Eet_Node *n; \ + \ + n = _eet_node_new(name, Eet_type); \ + if (!n) { return NULL; } \ + \ + n->data.value.Value = Value; \ + \ + return n; \ + } + +#define EET_NODE_STR_NEW(Eet_type, Name, Value, Type) \ + EAPI Eet_Node * \ + eet_node_ ## Name ## _new(const char *name, Type Value) \ + { \ + Eet_Node *n; \ + \ + n = _eet_node_new(name, Eet_type); \ + if (!n) { return NULL; } \ + \ + n->data.value.Value = eina_stringshare_add(Value); \ + \ + return n; \ + } + +EET_NODE_NEW(EET_T_CHAR, char, c, char) +EET_NODE_NEW(EET_T_SHORT, short, s, short) +EET_NODE_NEW(EET_T_INT, int, i, int) +EET_NODE_NEW(EET_T_LONG_LONG, long_long, l, long long) +EET_NODE_NEW(EET_T_FLOAT, float, f, float) +EET_NODE_NEW(EET_T_DOUBLE, double, d, double) +EET_NODE_NEW(EET_T_UCHAR, unsigned_char, uc, unsigned char) +EET_NODE_NEW(EET_T_USHORT, unsigned_short, us, unsigned short) +EET_NODE_NEW(EET_T_UINT, unsigned_int, ui, unsigned int) +EET_NODE_NEW(EET_T_ULONG_LONG, unsigned_long_long, ul, unsigned long long) +EET_NODE_STR_NEW(EET_T_STRING, string, str, const char *) +EET_NODE_STR_NEW(EET_T_INLINED_STRING, inlined_string, str, const char *) + +Eet_Node * +eet_node_null_new(const char *name) +{ + Eet_Node *n; + + n = _eet_node_new(name, EET_T_NULL); + if (!n) + return NULL; + + n->data.value.str = NULL; + + return n; +} + +Eet_Node * +eet_node_list_new(const char *name, + Eina_List *nodes) +{ + Eet_Node *n; + + n = _eet_node_new(name, EET_G_LIST); + if (!n) + return NULL; + + _eet_node_append(n, nodes); + + return n; +} + +Eet_Node * +eet_node_array_new(const char *name, + int count, + Eina_List *nodes) +{ + Eet_Node *n; + + n = _eet_node_new(name, EET_G_ARRAY); + if (!n) + return NULL; + + n->count = count; + + _eet_node_append(n, nodes); + + return n; +} + +Eet_Node * +eet_node_var_array_new(const char *name, + Eina_List *nodes) +{ + Eet_Node *n; + + n = _eet_node_new(name, EET_G_VAR_ARRAY); + if (!n) + return NULL; + + n->count = eina_list_count(nodes); + + _eet_node_append(n, nodes); + + return n; +} + +Eet_Node * +eet_node_hash_new(const char *name, + const char *key, + Eet_Node *node) +{ + Eina_List *nodes; + Eet_Node *n; + + if (!node) + return NULL; + + n = _eet_node_new(name, EET_G_HASH); + if (!n) + return NULL; + + n->key = eina_stringshare_add(key); + nodes = eina_list_append(NULL, node); + + _eet_node_append(n, nodes); + + return n; +} + +Eet_Node * +eet_node_struct_new(const char *name, + Eina_List *nodes) +{ + Eet_Node *n; + + n = _eet_node_new(name, EET_G_UNKNOWN); + if (!n) + return NULL; + + _eet_node_append(n, nodes); + + return n; +} + +Eet_Node * +eet_node_struct_child_new(const char *parent, + Eet_Node *child) +{ + Eet_Node *n; + + if (!child) return NULL; + + if (child->type != EET_G_UNKNOWN) + return child; + + n = _eet_node_new(parent, EET_G_UNKNOWN); + if (!n) + return NULL; + + _eet_node_append(n, eina_list_prepend(NULL, child)); + + return n; +} + +Eet_Node * +eet_node_children_get(Eet_Node *node) +{ + if (!node) return NULL; + return node->values; +} + +Eet_Node * +eet_node_next_get(Eet_Node *node) +{ + if (!node) return NULL; + return node->next; +} + +Eet_Node * +eet_node_parent_get(Eet_Node *node) +{ + if (!node) return NULL; + return node->parent; +} + +void +eet_node_list_append(Eet_Node *parent, + const char *name, + Eet_Node *child) +{ + const char *tmp; + Eet_Node *nn; + + if ((!parent) || (!child)) return; + tmp = eina_stringshare_add(name); + + for (nn = parent->values; nn; nn = nn->next) + if (nn->name == tmp && nn->type == EET_G_LIST) + { + Eet_Node *n; + + if (!nn->values) + nn->values = child; + else + { + for (n = nn->values; n->next; n = n->next) + ; + n->next = child; + } + + child->next = NULL; + + eina_stringshare_del(tmp); + + return; + } + + /* No list found, so create it. */ + nn = eet_node_list_new(tmp, eina_list_append(NULL, child)); + + /* And add it to the parent. */ + nn->next = parent->values; + parent->values = nn; + + eina_stringshare_del(tmp); +} + +void +eet_node_struct_append(Eet_Node *parent, + const char *name, + Eet_Node *child) +{ + const char *tmp; + Eet_Node *prev; + Eet_Node *nn; + + if ((!parent) || (!child)) return; + if (parent->type != EET_G_UNKNOWN) + { + ERR("[%s] is not a structure. Will not insert [%s] in it", + parent->name, + name); + eet_node_del(child); + return; + } + + tmp = eina_stringshare_add(name); + + for (prev = NULL, nn = parent->values; nn; prev = nn, nn = nn->next) + if (nn->name == tmp && nn->type == child->type) + { + if (prev) + prev->next = nn->next; + else + parent->values = nn->next; + + nn->next = NULL; + eet_node_del(nn); + + break; + } + + if (prev) + { + prev->next = child; + child->next = NULL; + } + else + { + child->next = NULL; + parent->values = child; + } + + eina_stringshare_del(tmp); +} + +void +eet_node_hash_add(Eet_Node *parent, + const char *name, + const char *key, + Eet_Node *child) +{ + Eet_Node *nn; + + if ((!parent) || (!child)) return; + + /* No list found, so create it. */ + nn = eet_node_hash_new(name, key, child); + + /* And add it to the parent. */ + nn->next = parent->values; + parent->values = nn; +} + +int +eet_node_type_get(Eet_Node *node) +{ + if (!node) return EET_T_UNKNOW; + return node->type; +} + +Eet_Node_Data * +eet_node_value_get(Eet_Node *node) +{ + if (!node) return NULL; + return &node->data; +} + +const char * +eet_node_name_get(Eet_Node *node) +{ + if (!node) return NULL; + return node->name; +} + +void +eet_node_del(Eet_Node *n) +{ + Eet_Node *nn; + Eet_Node *tmp; + + if (!n) + return; + + switch (n->type) + { + case EET_G_HASH: + eina_stringshare_del(n->key); + + case EET_G_UNKNOWN: + case EET_G_VAR_ARRAY: + case EET_G_ARRAY: + case EET_G_LIST: + for (nn = n->values; nn; ) + { + tmp = nn; + nn = nn->next; + eet_node_del(tmp); + } + break; + + case EET_T_STRING: + case EET_T_INLINED_STRING: + eina_stringshare_del(n->data.value.str); + break; + + case EET_T_CHAR: + case EET_T_SHORT: + case EET_T_INT: + case EET_T_LONG_LONG: + case EET_T_FLOAT: + case EET_T_DOUBLE: + case EET_T_UCHAR: + case EET_T_USHORT: + case EET_T_UINT: + break; + } + + eina_stringshare_del(n->name); + eet_node_free(n); +} + +static const char *eet_node_dump_g_name[6] = { + "struct", + "array", + "var_array", + "list", + "hash", + "???" +}; + +static const char *eet_node_dump_t_name[14][2] = { + { "???: ", "???" }, + { "char: ", "%hhi" }, + { "short: ", "%hi" }, + { "int: ", "%i" }, + { "long_long: ", "%lli" }, + { "float: ", "%1.25f" }, + { "double: ", "%1.25f" }, + { "uchar: ", "%hhu" }, + { "ushort: ", "%i" }, + { "uint: ", "%u" }, + { "ulong_long: ", "%llu" }, + { "null", "" } +}; + +static void +eet_node_dump_level(int level, + Eet_Dump_Callback dumpfunc, + void *dumpdata) +{ + int i; + + for (i = 0; i < level; i++) dumpfunc(dumpdata, " "); +} + +static char * +eet_node_string_escape(const char *str) +{ + char *s, *sp; + const char *strp; + int sz = 0; + + for (strp = str; *strp; strp++) + { + if (*strp == '\"') + sz += 2; + else if (*strp == '\\') + sz += 2; + else if (*strp == '\n') + sz += 2; + else + sz += 1; + } + s = malloc(sz + 1); + if (!s) + return NULL; + + for (strp = str, sp = s; *strp; strp++, sp++) + { + if (*strp == '\"' + || *strp == '\\' + || *strp == '\n') + { + *sp = '\\'; + sp++; + } + + if (*strp == '\n') + *sp = 'n'; + else + *sp = *strp; + } + *sp = 0; + return s; +} + +static void +eet_node_dump_string_escape(void *dumpdata, + Eet_Dump_Callback dumpfunc, + const char *str) +{ + char *s; + + s = eet_node_string_escape(str); + if (!s) + return; + + dumpfunc(dumpdata, s); + free(s); +} + +static void +eet_node_dump_simple_type(Eet_Node *n, + int level, + Eet_Dump_Callback dumpfunc, + void *dumpdata) +{ + const char *type_name = NULL; + char tbuf[256]; + + eet_node_dump_level(level, dumpfunc, dumpdata); + dumpfunc(dumpdata, "value \""); + eet_node_dump_string_escape(dumpdata, dumpfunc, n->name); + dumpfunc(dumpdata, "\" "); + +#ifdef EET_T_TYPE +# undef EET_T_TYPE +#endif /* ifdef EET_T_TYPE */ + +#define EET_T_TYPE(Eet_Type, Type) \ +case Eet_Type: \ +{ \ + dumpfunc(dumpdata, eet_node_dump_t_name[Eet_Type][0]); \ + snprintf(tbuf, \ + sizeof (tbuf), \ + eet_node_dump_t_name[Eet_Type][1], \ + n->data.value.Type); \ + dumpfunc(dumpdata, tbuf); \ + break; \ +} + + switch (n->type) + { + EET_T_TYPE(EET_T_CHAR, c); + EET_T_TYPE(EET_T_SHORT, s); + EET_T_TYPE(EET_T_INT, i); + EET_T_TYPE(EET_T_LONG_LONG, l); + EET_T_TYPE(EET_T_FLOAT, f); + EET_T_TYPE(EET_T_DOUBLE, d); + EET_T_TYPE(EET_T_UCHAR, uc); + EET_T_TYPE(EET_T_USHORT, us); + EET_T_TYPE(EET_T_UINT, ui); + EET_T_TYPE(EET_T_ULONG_LONG, ul); + + case EET_T_INLINED_STRING: + type_name = "inlined: \""; + + case EET_T_STRING: + if (!type_name) + type_name = "string: \""; + + dumpfunc(dumpdata, type_name); + eet_node_dump_string_escape(dumpdata, dumpfunc, n->data.value.str); + dumpfunc(dumpdata, "\""); + break; + + case EET_T_NULL: + dumpfunc(dumpdata, "null"); + break; + + default: + dumpfunc(dumpdata, "???: ???"); + break; + } + + dumpfunc(dumpdata, ";\n"); +} + +static void +eet_node_dump_group_start(int level, + Eet_Dump_Callback dumpfunc, + void *dumpdata, + int group_type, + const char *name) +{ + int chnk_type; + + chnk_type = (group_type >= EET_G_UNKNOWN && group_type <= EET_G_HASH) ? + group_type : EET_G_LAST; + + eet_node_dump_level(level, dumpfunc, dumpdata); + dumpfunc(dumpdata, "group \""); + eet_node_dump_string_escape(dumpdata, dumpfunc, name); + dumpfunc(dumpdata, "\" "); + + dumpfunc(dumpdata, eet_node_dump_g_name[chnk_type - EET_G_UNKNOWN]); + dumpfunc(dumpdata, " {\n"); +} + +static void +eet_node_dump_group_end(int level, + Eet_Dump_Callback dumpfunc, + void *dumpdata) +{ + eet_node_dump_level(level, dumpfunc, dumpdata); + dumpfunc(dumpdata, "}\n"); +} + +void +eet_node_dump(Eet_Node *n, + int dumplevel, + Eet_Dump_Callback dumpfunc, + void *dumpdata) +{ + Eet_Node *it; + + if (!n) + return; + + switch (n->type) + { + case EET_G_VAR_ARRAY: + case EET_G_ARRAY: + case EET_G_UNKNOWN: + case EET_G_HASH: + case EET_G_LIST: + eet_node_dump_group_start(dumplevel, + dumpfunc, + dumpdata, + n->type, + n->name); + + if (n->type == EET_G_VAR_ARRAY + || n->type == EET_G_ARRAY) + { + char tbuf[256]; + + eet_node_dump_level(dumplevel, dumpfunc, dumpdata); + dumpfunc(dumpdata, " count "); + eina_convert_itoa(n->count, tbuf); + dumpfunc(dumpdata, tbuf); + dumpfunc(dumpdata, ";\n"); + } + else if (n->type == EET_G_HASH) + { + eet_node_dump_level(dumplevel, dumpfunc, dumpdata); + dumpfunc(dumpdata, " key \""); + eet_node_dump_string_escape(dumpdata, dumpfunc, n->key); + dumpfunc(dumpdata, "\";\n"); + } + + for (it = n->values; it; it = it->next) + eet_node_dump(it, dumplevel + 2, dumpfunc, dumpdata); + + eet_node_dump_group_end(dumplevel, dumpfunc, dumpdata); + break; + + case EET_T_STRING: + case EET_T_INLINED_STRING: + case EET_T_CHAR: + case EET_T_SHORT: + case EET_T_INT: + case EET_T_LONG_LONG: + case EET_T_FLOAT: + case EET_T_DOUBLE: + case EET_T_UCHAR: + case EET_T_USHORT: + case EET_T_UINT: + case EET_T_ULONG_LONG: + eet_node_dump_simple_type(n, dumplevel, dumpfunc, dumpdata); + break; + } +} + +void * +eet_node_walk(void *parent, + const char *name, + Eet_Node *root, + Eet_Node_Walk *cb, + void *user_data) +{ + Eet_Node *it; + void *me = NULL; + int i; + + if (!root) + { + if (parent) + cb->struct_add(parent, name, NULL, user_data); + + return NULL; + } + + switch (root->type) + { + case EET_G_UNKNOWN: + me = cb->struct_alloc(root->name, user_data); + + for (it = root->values; it; it = it->next) + eet_node_walk(me, it->name, it, cb, user_data); + + break; + + case EET_G_VAR_ARRAY: + case EET_G_ARRAY: + me = cb->array(root->type == EET_G_VAR_ARRAY ? EINA_TRUE : EINA_FALSE, + root->name, root->count, user_data); + + for (i = 0, it = root->values; it; it = it->next) + cb->insert(me, i++, eet_node_walk(NULL, + NULL, + it, + cb, + user_data), user_data); + + break; + + case EET_G_LIST: + me = cb->list(root->name, user_data); + + for (it = root->values; it; it = it->next) + cb->append(me, eet_node_walk(NULL, + NULL, + it, + cb, + user_data), user_data); + + break; + + case EET_G_HASH: + if (!parent) + return NULL; + + return cb->hash(parent, root->name, root->key, + eet_node_walk(NULL, + NULL, + root->values, + cb, + user_data), user_data); + + case EET_T_STRING: + case EET_T_INLINED_STRING: + case EET_T_CHAR: + case EET_T_SHORT: + case EET_T_INT: + case EET_T_LONG_LONG: + case EET_T_FLOAT: + case EET_T_DOUBLE: + case EET_T_UCHAR: + case EET_T_USHORT: + case EET_T_UINT: + case EET_T_ULONG_LONG: + me = cb->simple(root->type, &root->data, user_data); + break; + } + + if (parent) + cb->struct_add(parent, name, me, user_data); + + return me; +} + +int +eet_node_init(void) +{ + const char *choice; + const char *tmp; + +#ifdef EINA_DEFAULT_MEMPOOL + choice = "pass_through"; +#else + choice = "chained_mempool"; +#endif + tmp = getenv("EINA_MEMPOOL"); + if (tmp && tmp[0]) + choice = tmp; + + _eet_node_mp = + eina_mempool_add(choice, "eet-node-alloc", NULL, sizeof(Eet_Node), 32); + + return _eet_node_mp ? 1 : 0; +} + +void +eet_node_shutdown(void) +{ + eina_mempool_del(_eet_node_mp); + _eet_node_mp = NULL; +} + diff --git a/src/lib/eet_utils.c b/src/lib/eet_utils.c index 1785076..b04ad1b 100644 --- a/src/lib/eet_utils.c +++ b/src/lib/eet_utils.c @@ -1,6 +1,6 @@ -/* - * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 - */ +#ifdef HAVE_CONFIG_H +# include +#endif /* ifdef HAVE_CONFIG_H */ #include #include @@ -9,195 +9,28 @@ #include "Eet_private.h" int -_eet_hash_gen(const char *key, int hash_size) +_eet_hash_gen(const char *key, + int hash_size) { - int hash_num = 0; - int value, i; - unsigned char *ptr; - - const int masks[9] = - { - 0x00, - 0x01, - 0x03, - 0x07, - 0x0f, - 0x1f, - 0x3f, - 0x7f, - 0xff - }; + int hash_num = 0; + int value, i; + int mask; + unsigned char *ptr; /* no string - index 0 */ - if (!key) return 0; + if (!key) + return 0; /* calc hash num */ for (i = 0, ptr = (unsigned char *)key, value = (int)(*ptr); - value; - ptr++, i++, value = (int)(*ptr)) + value; + ptr++, i++, value = (int)(*ptr)) hash_num ^= (value | (value << 8)) >> (i & 0x7); /* mask it */ - hash_num &= masks[hash_size]; + mask = (1 << hash_size) - 1; + hash_num &= mask; /* return it */ return hash_num; } -/* On Windows (using MinGW or VC++), printf-like functions */ -/* rely on MSVCRT, which does not fully support the C99 */ -/* specifications. In particular, they do not support the */ -/* modifier character %a. */ - - -/* That function converts a string created by a valid %a */ -/* modifier to a double. */ -/* */ -/* The string must have the following format: */ -/* */ -/* [-]0xh.hhhhhp[+-]e */ -/* */ -/* where e is a decimal number. */ -/* If n is the number of cyphers after the point, the */ -/* returned mantisse and exponents are */ -/* */ -/* mantisse: [-]hhhhhh */ -/* exponent: 2^([+-]e - 4 * n) */ -int -_eet_string_to_double_convert(const char *src, long long *m, long *e) -{ - const char *str; - long long mantisse; - long exponent; - int nbr_decimals; - int sign; - - str = src; - sign = +1; - - if (*str == '-') - { - sign = -1; - str++; - } - if (*str == '0') - { - str++; - if (*str == 'x') - str++; - else - { - fprintf(stderr, "[Eet] Error 1 during conversion of '%s'\n", src); - return 0; - } - } - else - { - fprintf(stderr, "[Eet] Error 2 during conversion of '%s'\n", src); - return 0; - } - - nbr_decimals = 0; - mantisse = (*str >= 'a') ? *str - 'a' + 10 : *str - '0'; - str++; - if (*str == '.') - { - str++; - while (*str != 'p') - { - mantisse <<= 4; - mantisse += (*str >= 'a') ? *str - 'a' + 10 : *str - '0'; - str++; - nbr_decimals++; - } - } - if (sign < 0) - mantisse = -mantisse; - if (*str != 'p') - { - fprintf(stderr, "[Eet] Error 3 during conversion '%s'\n", src); - return 0; - } - sign = +1; - str++; - if (*str == '-') - { - sign = -1; - str++; - } - else if (*str == '+') str++; - - exponent = 0; - while (*str != '\0') - { - exponent *= 10; - exponent += *str - '0'; - str++; - } - - if (sign < 0) - exponent = -exponent; - - *m = mantisse; - *e = exponent - (nbr_decimals << 2); - - return 1; -} - -/* That function converts a double to a string that as the */ -/* following format: */ -/* */ -/* [-]0xh.hhhhhp[+-]e */ -/* */ -/* where h is a hexadecimal number and e a decimal number. */ -void -_eet_double_to_string_convert(char des[128], double d) -{ - static const char look_up_table[] = {'0', '1', '2', '3', '4', - '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f'}; - int p; - int i; - - if (d < 0.0) - { - *(des++) = '-'; - d = -d; - } - - d = frexp(d, &p); - - if (p) - { - d *= 2; - p -= 1; - } - - *(des++) = '0'; - *(des++) = 'x'; - *(des++) = look_up_table[(size_t)d]; - *(des++) = '.'; - - for (i = 0; i < 16; i++) - { - d -= floor(d); - d *= 16; - *(des++) = look_up_table[(size_t)d]; - } - - while (*(des - 1) == '0') - des--; - - if (*(des - 1) == '.') - des--; - - *(des++) = 'p'; - if (p < 0) - { - *(des++) = '-'; - p = -p; - } - else - *(des++) = '+'; - - snprintf(des, 128, "%d", p); -} diff --git a/src/lib/lz4/README b/src/lib/lz4/README new file mode 100644 index 0000000..0abb857 --- /dev/null +++ b/src/lib/lz4/README @@ -0,0 +1,7 @@ +This iz the lz4 tree copied in: + http://lz4.googlecode.com/svn/trunk +by: + yann.collet.73@gmail.com +Copyright/licensing info in source files here. + +this was from revsion 66. diff --git a/src/lib/lz4/lz4.c b/src/lib/lz4/lz4.c new file mode 100644 index 0000000..eeefa67 --- /dev/null +++ b/src/lib/lz4/lz4.c @@ -0,0 +1,863 @@ +/* + LZ4 - Fast LZ compression algorithm + Copyright (C) 2011-2012, Yann Collet. + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html + - LZ4 source repository : http://code.google.com/p/lz4/ +*/ + +//************************************** +// Tuning parameters +//************************************** +// MEMORY_USAGE : +// Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) +// Increasing memory usage improves compression ratio +// Reduced memory usage can improve speed, due to cache effect +// Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache +#define MEMORY_USAGE 14 + +// NOTCOMPRESSIBLE_DETECTIONLEVEL : +// Decreasing this value will make the algorithm skip faster data segments considered "incompressible" +// This may decrease compression ratio dramatically, but will be faster on incompressible data +// Increasing this value will make the algorithm search more before declaring a segment "incompressible" +// This could improve compression a bit, but will be slower on incompressible data +// The default value (6) is recommended +#define NOTCOMPRESSIBLE_DETECTIONLEVEL 6 + +// BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE : +// This will provide a small boost to performance for big endian cpu, but the resulting compressed stream will be incompatible with little-endian CPU. +// You can set this option to 1 in situations where data will remain within closed environment +// This option is useless on Little_Endian CPU (such as x86) +//#define BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE 1 + + + +//************************************** +// CPU Feature Detection +//************************************** +// 32 or 64 bits ? +#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || defined(__LP64__) || defined(_LP64) ) // Detects 64 bits mode +# define LZ4_ARCH64 1 +#else +# define LZ4_ARCH64 0 +#endif + +// Little Endian or Big Endian ? +// Note : overwrite the below #define if you know your architecture endianess +#if (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) || defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC) || defined(PPC) || defined(__powerpc__) || defined(__powerpc) || defined(powerpc) || ((defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))) ) +# define LZ4_BIG_ENDIAN 1 +#else +// Little Endian assumed. PDP Endian and other very rare endian format are unsupported. +#endif + +// Unaligned memory access is automatically enabled for "common" CPU, such as x86. +// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected +// If you know your target CPU supports unaligned memory access, you may want to force this option manually to improve performance +#if defined(__ARM_FEATURE_UNALIGNED) +# define LZ4_FORCE_UNALIGNED_ACCESS 1 +#endif + +// Define this parameter if your target system or compiler does not support hardware bit count +#if defined(_MSC_VER) && defined(_WIN32_WCE) // Visual Studio for Windows CE does not support Hardware bit count +# define LZ4_FORCE_SW_BITCOUNT +#endif + + +//************************************** +// Compiler Options +//************************************** +#if __STDC_VERSION__ >= 199901L // C99 +/* "restrict" is a known keyword */ +#else +# define restrict // Disable restrict +#endif + +#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +#ifdef _MSC_VER // Visual Studio +# define inline __forceinline // Visual is not C99, but supports some kind of inline +# include // For Visual 2005 +# if LZ4_ARCH64 // 64-bit +# pragma intrinsic(_BitScanForward64) // For Visual 2005 +# pragma intrinsic(_BitScanReverse64) // For Visual 2005 +# else +# pragma intrinsic(_BitScanForward) // For Visual 2005 +# pragma intrinsic(_BitScanReverse) // For Visual 2005 +# endif +#endif + +#ifdef _MSC_VER +# define lz4_bswap16(x) _byteswap_ushort(x) +#else +# define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8))) +#endif + +#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__) +# define expect(expr,value) (__builtin_expect ((expr),(value)) ) +#else +# define expect(expr,value) (expr) +#endif + +#define likely(expr) expect((expr) != 0, 1) +#define unlikely(expr) expect((expr) != 0, 0) + + +//************************************** +// Includes +//************************************** +#include // for malloc +#include // for memset +#include "lz4.h" + + +//************************************** +// Basic Types +//************************************** +#if defined(_MSC_VER) // Visual Studio does not support 'stdint' natively +# define BYTE unsigned __int8 +# define U16 unsigned __int16 +# define U32 unsigned __int32 +# define S32 __int32 +# define U64 unsigned __int64 +#else +# include +# define BYTE uint8_t +# define U16 uint16_t +# define U32 uint32_t +# define S32 int32_t +# define U64 uint64_t +#endif + +#ifndef LZ4_FORCE_UNALIGNED_ACCESS +# pragma pack(push, 1) +#endif + +typedef struct _U16_S { U16 v; } U16_S; +typedef struct _U32_S { U32 v; } U32_S; +typedef struct _U64_S { U64 v; } U64_S; + +#ifndef LZ4_FORCE_UNALIGNED_ACCESS +# pragma pack(pop) +#endif + +#define A64(x) (((U64_S *)(x))->v) +#define A32(x) (((U32_S *)(x))->v) +#define A16(x) (((U16_S *)(x))->v) + + +//************************************** +// Constants +//************************************** +#define MINMATCH 4 + +#define HASH_LOG (MEMORY_USAGE-2) +#define HASHTABLESIZE (1 << HASH_LOG) +#define HASH_MASK (HASHTABLESIZE - 1) + +#define SKIPSTRENGTH (NOTCOMPRESSIBLE_DETECTIONLEVEL>2?NOTCOMPRESSIBLE_DETECTIONLEVEL:2) +#define STACKLIMIT 13 +#define HEAPMODE (HASH_LOG>STACKLIMIT) // Defines if memory is allocated into the stack (local variable), or into the heap (malloc()). +#define COPYLENGTH 8 +#define LASTLITERALS 5 +#define MFLIMIT (COPYLENGTH+MINMATCH) +#define MINLENGTH (MFLIMIT+1) + +#define MAXD_LOG 16 +#define MAX_DISTANCE ((1 << MAXD_LOG) - 1) + +#define ML_BITS 4 +#define ML_MASK ((1U<> ((MINMATCH*8)-HASH_LOG)) +#define LZ4_HASH_VALUE(p) LZ4_HASH_FUNCTION(A32(p)) +#define LZ4_WILDCOPY(s,d,e) do { LZ4_COPYPACKET(s,d) } while (d>3); + #elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_clzll(val) >> 3); + #else + int r; + if (!(val>>32)) { r=4; } else { r=0; val>>=32; } + if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } + r += (!val); + return r; + #endif +#else + #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanForward64( &r, val ); + return (int)(r>>3); + #elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_ctzll(val) >> 3); + #else + static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; + return DeBruijnBytePos[((U64)((val & -val) * 0x0218A392CDABBD3F)) >> 58]; + #endif +#endif +} + +#else + +static inline int LZ4_NbCommonBytes (register U32 val) +{ +#if defined(LZ4_BIG_ENDIAN) + #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanReverse( &r, val ); + return (int)(r>>3); + #elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_clz(val) >> 3); + #else + int r; + if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; } + r += (!val); + return r; + #endif +#else + #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanForward( &r, val ); + return (int)(r>>3); + #elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_ctz(val) >> 3); + #else + static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; + return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; + #endif +#endif +} + +#endif + + + +//****************************** +// Compression functions +//****************************** + +// LZ4_compressCtx : +// ----------------- +// Compress 'isize' bytes from 'source' into an output buffer 'dest' of maximum size 'maxOutputSize'. +// If it cannot achieve it, compression will stop, and result of the function will be zero. +// return : the number of bytes written in buffer 'dest', or 0 if the compression fails + +static inline int LZ4_compressCtx(void** ctx, + const char* source, + char* dest, + int isize, + int maxOutputSize) +{ +#if HEAPMODE + struct refTables *srt = (struct refTables *) (*ctx); + HTYPE* HashTable; +#else + HTYPE HashTable[HASHTABLESIZE] = {0}; +#endif + + const BYTE* ip = (BYTE*) source; + INITBASE(base); + const BYTE* anchor = ip; + const BYTE* const iend = ip + isize; + const BYTE* const mflimit = iend - MFLIMIT; +#define matchlimit (iend - LASTLITERALS) + + BYTE* op = (BYTE*) dest; + BYTE* const oend = op + maxOutputSize; + + int len, length; + const int skipStrength = SKIPSTRENGTH; + U32 forwardH; + + + // Init + if (isizehashTable); + memset((void*)HashTable, 0, sizeof(srt->hashTable)); +#else + (void) ctx; +#endif + + + // First Byte + HashTable[LZ4_HASH_VALUE(ip)] = ip - base; + ip++; forwardH = LZ4_HASH_VALUE(ip); + + // Main Loop + for ( ; ; ) + { + int findMatchAttempts = (1U << skipStrength) + 3; + const BYTE* forwardIp = ip; + const BYTE* ref; + BYTE* token; + + // Find a match + do { + U32 h = forwardH; + int step = findMatchAttempts++ >> skipStrength; + ip = forwardIp; + forwardIp = ip + step; + + if unlikely(forwardIp > mflimit) { goto _last_literals; } + + forwardH = LZ4_HASH_VALUE(forwardIp); + ref = base + HashTable[h]; + HashTable[h] = ip - base; + + } while ((ref < ip - MAX_DISTANCE) || (A32(ref) != A32(ip))); + + // Catch up + while ((ip>anchor) && (ref>(BYTE*)source) && unlikely(ip[-1]==ref[-1])) { ip--; ref--; } + + // Encode Literal length + length = (int)(ip - anchor); + token = op++; + if unlikely(op + length + (2 + 1 + LASTLITERALS) + (length>>8) >= oend) return 0; // Check output limit +#ifdef _MSC_VER + if (length>=(int)RUN_MASK) + { + int len = length-RUN_MASK; + *token=(RUN_MASK<254) + { + do { *op++ = 255; len -= 255; } while (len>254); + *op++ = (BYTE)len; + memcpy(op, anchor, length); + op += length; + goto _next_match; + } + else + *op++ = (BYTE)len; + } + else *token = (length<=(int)RUN_MASK) { *token=(RUN_MASK< 254 ; len-=255) *op++ = 255; *op++ = (BYTE)len; } + else *token = (length<>8) >= oend) return 0; // Check output limit + if (len>=(int)ML_MASK) { *token+=ML_MASK; len-=ML_MASK; for(; len > 509 ; len-=510) { *op++ = 255; *op++ = 255; } if (len > 254) { len-=255; *op++ = 255; } *op++ = (BYTE)len; } + else *token += len; + + // Test end of chunk + if (ip > mflimit) { anchor = ip; break; } + + // Fill table + HashTable[LZ4_HASH_VALUE(ip-2)] = ip - 2 - base; + + // Test next position + ref = base + HashTable[LZ4_HASH_VALUE(ip)]; + HashTable[LZ4_HASH_VALUE(ip)] = ip - base; + if ((ref > ip - (MAX_DISTANCE + 1)) && (A32(ref) == A32(ip))) { token = op++; *token=0; goto _next_match; } + + // Prepare next loop + anchor = ip++; + forwardH = LZ4_HASH_VALUE(ip); + } + +_last_literals: + // Encode Last Literals + { + int lastRun = (int)(iend - anchor); + if (((char*)op - dest) + lastRun + 1 + ((lastRun-15)/255) >= maxOutputSize) return 0; + if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK< 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; } + else *op++ = (lastRun<> ((MINMATCH*8)-HASHLOG64K)) +#define LZ4_HASH64K_VALUE(p) LZ4_HASH64K_FUNCTION(A32(p)) +static inline int LZ4_compress64kCtx(void** ctx, + const char* source, + char* dest, + int isize, + int maxOutputSize) +{ +#if HEAPMODE + struct refTables *srt = (struct refTables *) (*ctx); + U16* HashTable; +#else + U16 HashTable[HASH64KTABLESIZE] = {0}; +#endif + + const BYTE* ip = (BYTE*) source; + const BYTE* anchor = ip; + const BYTE* const base = ip; + const BYTE* const iend = ip + isize; + const BYTE* const mflimit = iend - MFLIMIT; +#define matchlimit (iend - LASTLITERALS) + + BYTE* op = (BYTE*) dest; + BYTE* const oend = op + maxOutputSize; + + int len, length; + const int skipStrength = SKIPSTRENGTH; + U32 forwardH; + + + // Init + if (isizehashTable); + memset((void*)HashTable, 0, sizeof(srt->hashTable)); +#else + (void) ctx; +#endif + + + // First Byte + ip++; forwardH = LZ4_HASH64K_VALUE(ip); + + // Main Loop + for ( ; ; ) + { + int findMatchAttempts = (1U << skipStrength) + 3; + const BYTE* forwardIp = ip; + const BYTE* ref; + BYTE* token; + + // Find a match + do { + U32 h = forwardH; + int step = findMatchAttempts++ >> skipStrength; + ip = forwardIp; + forwardIp = ip + step; + + if (forwardIp > mflimit) { goto _last_literals; } + + forwardH = LZ4_HASH64K_VALUE(forwardIp); + ref = base + HashTable[h]; + HashTable[h] = (U16)(ip - base); + + } while (A32(ref) != A32(ip)); + + // Catch up + while ((ip>anchor) && (ref>(BYTE*)source) && (ip[-1]==ref[-1])) { ip--; ref--; } + + // Encode Literal length + length = (int)(ip - anchor); + token = op++; + if unlikely(op + length + (2 + 1 + LASTLITERALS) + (length>>8) >= oend) return 0; // Check output limit +#ifdef _MSC_VER + if (length>=(int)RUN_MASK) + { + int len = length-RUN_MASK; + *token=(RUN_MASK<254) + { + do { *op++ = 255; len -= 255; } while (len>254); + *op++ = (BYTE)len; + memcpy(op, anchor, length); + op += length; + goto _next_match; + } + else + *op++ = (BYTE)len; + } + else *token = (length<=(int)RUN_MASK) { *token=(RUN_MASK< 254 ; len-=255) *op++ = 255; *op++ = (BYTE)len; } + else *token = (length<>8) >= oend) return 0; // Check output limit + if (len>=(int)ML_MASK) { *token+=ML_MASK; len-=ML_MASK; for(; len > 509 ; len-=510) { *op++ = 255; *op++ = 255; } if (len > 254) { len-=255; *op++ = 255; } *op++ = (BYTE)len; } + else *token += len; + + // Test end of chunk + if (ip > mflimit) { anchor = ip; break; } + + // Fill table + HashTable[LZ4_HASH64K_VALUE(ip-2)] = (U16)(ip - 2 - base); + + // Test next position + ref = base + HashTable[LZ4_HASH64K_VALUE(ip)]; + HashTable[LZ4_HASH64K_VALUE(ip)] = (U16)(ip - base); + if (A32(ref) == A32(ip)) { token = op++; *token=0; goto _next_match; } + + // Prepare next loop + anchor = ip++; + forwardH = LZ4_HASH64K_VALUE(ip); + } + +_last_literals: + // Encode Last Literals + { + int lastRun = (int)(iend - anchor); + if (((char*)op - dest) + lastRun + 1 + ((lastRun)>>8) >= maxOutputSize) return 0; + if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK< 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; } + else *op++ = (lastRun<>ML_BITS)) == RUN_MASK) { for (;(len=*ip++)==255;length+=255){} length += len; } + + // copy literals + cpy = op+length; + if unlikely(cpy>oend-COPYLENGTH) + { + if (cpy > oend) goto _output_error; // Error : request to write beyond destination buffer + memcpy(op, ip, length); + ip += length; + break; // Necessarily EOF + } + LZ4_WILDCOPY(ip, op, cpy); ip -= (op-cpy); op = cpy; + + // get offset + LZ4_READ_LITTLEENDIAN_16(ref,cpy,ip); ip+=2; + if (ref < (BYTE* const)dest) goto _output_error; // Error : offset create reference outside destination buffer + + // get matchlength + if ((length=(token&ML_MASK)) == ML_MASK) { for (;*ip==255;length+=255) {ip++;} length += *ip++; } + + // copy repeated sequence + if unlikely(op-refoend-COPYLENGTH) + { + if (cpy > oend) goto _output_error; // Error : request to write beyond destination buffer + LZ4_SECURECOPY(ref, op, (oend-COPYLENGTH)); + while(op>ML_BITS)) == RUN_MASK) { int s=255; while ((ipoend-COPYLENGTH) || (ip+length>iend-COPYLENGTH)) + { + if (cpy > oend) goto _output_error; // Error : request to write beyond destination buffer + if (ip+length > iend) goto _output_error; // Error : request to read beyond source buffer + memcpy(op, ip, length); + op += length; + ip += length; + if (ipoend-COPYLENGTH) + { + if (cpy > oend) goto _output_error; // Error : request to write outside of destination buffer + LZ4_SECURECOPY(ref, op, (oend-COPYLENGTH)); + while(op= 199901L // C99 + /* "restrict" is a known keyword */ +#else +#define restrict // Disable restrict +#endif + +#ifdef _MSC_VER +#define inline __forceinline // Visual is not C99, but supports some kind of inline +#include // For Visual 2005 +# if LZ4_ARCH64 // 64-bit +# pragma intrinsic(_BitScanForward64) // For Visual 2005 +# pragma intrinsic(_BitScanReverse64) // For Visual 2005 +# else +# pragma intrinsic(_BitScanForward) // For Visual 2005 +# pragma intrinsic(_BitScanReverse) // For Visual 2005 +# endif +#endif + +#ifdef _MSC_VER // Visual Studio +#define lz4_bswap16(x) _byteswap_ushort(x) +#else +#define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8))) +#endif + + +//************************************** +// Includes +//************************************** +#include // calloc, free +#include // memset, memcpy +#include "lz4hc.h" + +#define ALLOCATOR(s) calloc(1,s) +#define FREEMEM free +#define MEM_INIT memset + + +//************************************** +// Basic Types +//************************************** +#if defined(_MSC_VER) // Visual Studio does not support 'stdint' natively +#define BYTE unsigned __int8 +#define U16 unsigned __int16 +#define U32 unsigned __int32 +#define S32 __int32 +#define U64 unsigned __int64 +#else +#include +#define BYTE uint8_t +#define U16 uint16_t +#define U32 uint32_t +#define S32 int32_t +#define U64 uint64_t +#endif + +#ifndef LZ4_FORCE_UNALIGNED_ACCESS +#pragma pack(push, 1) +#endif + +typedef struct _U16_S { U16 v; } U16_S; +typedef struct _U32_S { U32 v; } U32_S; +typedef struct _U64_S { U64 v; } U64_S; + +#ifndef LZ4_FORCE_UNALIGNED_ACCESS +#pragma pack(pop) +#endif + +#define A64(x) (((U64_S *)(x))->v) +#define A32(x) (((U32_S *)(x))->v) +#define A16(x) (((U16_S *)(x))->v) + + +//************************************** +// Constants +//************************************** +#define MINMATCH 4 + +#define DICTIONARY_LOGSIZE 16 +#define MAXD (1<> ((MINMATCH*8)-HASH_LOG)) +#define HASH_VALUE(p) HASH_FUNCTION(*(U32*)(p)) +#define HASH_POINTER(p) (HashTable[HASH_VALUE(p)] + base) +#define DELTANEXT(p) chainTable[(size_t)(p) & MAXD_MASK] +#define GETNEXT(p) ((p) - (size_t)DELTANEXT(p)) +#define ADD_HASH(p) { size_t delta = (p) - HASH_POINTER(p); if (delta>MAX_DISTANCE) delta = MAX_DISTANCE; DELTANEXT(p) = (U16)delta; HashTable[HASH_VALUE(p)] = (p) - base; } + + +//************************************** +// Private functions +//************************************** +#if LZ4_ARCH64 + +inline static int LZ4_NbCommonBytes (register U64 val) +{ +#if defined(LZ4_BIG_ENDIAN) + #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanReverse64( &r, val ); + return (int)(r>>3); + #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_clzll(val) >> 3); + #else + int r; + if (!(val>>32)) { r=4; } else { r=0; val>>=32; } + if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } + r += (!val); + return r; + #endif +#else + #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanForward64( &r, val ); + return (int)(r>>3); + #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_ctzll(val) >> 3); + #else + static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; + return DeBruijnBytePos[((U64)((val & -val) * 0x0218A392CDABBD3F)) >> 58]; + #endif +#endif +} + +#else + +inline static int LZ4_NbCommonBytes (register U32 val) +{ +#if defined(LZ4_BIG_ENDIAN) + #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanReverse( &r, val ); + return (int)(r>>3); + #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_clz(val) >> 3); + #else + int r; + if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; } + r += (!val); + return r; + #endif +#else + #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanForward( &r, val ); + return (int)(r>>3); + #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_ctz(val) >> 3); + #else + static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; + return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; + #endif +#endif +} + +#endif + + +inline static int LZ4HC_Init (LZ4HC_Data_Structure* hc4, const BYTE* base) +{ + MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable)); + MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable)); + hc4->nextToUpdate = base + LZ4_ARCH64; + hc4->base = base; + return 1; +} + + +inline static void* LZ4HC_Create (const BYTE* base) +{ + void* hc4 = ALLOCATOR(sizeof(LZ4HC_Data_Structure)); + + LZ4HC_Init (hc4, base); + return hc4; +} + + +inline static int LZ4HC_Free (void** LZ4HC_Data) +{ + FREEMEM(*LZ4HC_Data); + *LZ4HC_Data = NULL; + return (1); +} + + +inline static void LZ4HC_Insert (LZ4HC_Data_Structure* hc4, const BYTE* ip) +{ + U16* chainTable = hc4->chainTable; + HTYPE* HashTable = hc4->hashTable; + INITBASE(base,hc4->base); + + while(hc4->nextToUpdate < ip) + { + ADD_HASH(hc4->nextToUpdate); + hc4->nextToUpdate++; + } +} + + +inline static int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4, const BYTE* ip, const BYTE* const matchlimit, const BYTE** matchpos) +{ + U16* const chainTable = hc4->chainTable; + HTYPE* const HashTable = hc4->hashTable; + const BYTE* ref; + INITBASE(base,hc4->base); + int nbAttempts=MAX_NB_ATTEMPTS; + int ml=0; + + // HC4 match finder + LZ4HC_Insert(hc4, ip); + ref = HASH_POINTER(ip); + while ((ref > (ip-MAX_DISTANCE)) && (nbAttempts)) + { + nbAttempts--; + if (*(ref+ml) == *(ip+ml)) + if (*(U32*)ref == *(U32*)ip) + { + const BYTE* reft = ref+MINMATCH; + const BYTE* ipt = ip+MINMATCH; + + while (ipt ml) { ml = (int)(ipt-ip); *matchpos = ref; } + } + ref = GETNEXT(ref); + } + + return ml; +} + + +inline static int LZ4HC_InsertAndGetWiderMatch (LZ4HC_Data_Structure* hc4, const BYTE* ip, const BYTE* startLimit, const BYTE* matchlimit, int longest, const BYTE** matchpos, const BYTE** startpos) +{ + U16* const chainTable = hc4->chainTable; + HTYPE* const HashTable = hc4->hashTable; + INITBASE(base,hc4->base); + const BYTE* ref; + int nbAttempts = MAX_NB_ATTEMPTS; + int delta = (int)(ip-startLimit); + + // First Match + LZ4HC_Insert(hc4, ip); + ref = HASH_POINTER(ip); + + while ((ref > ip-MAX_DISTANCE) && (ref >= hc4->base) && (nbAttempts)) + { + nbAttempts--; + if (*(startLimit + longest) == *(ref - delta + longest)) + if (*(U32*)ref == *(U32*)ip) + { + const BYTE* reft = ref+MINMATCH; + const BYTE* ipt = ip+MINMATCH; + const BYTE* startt = ip; + + while (iptstartLimit) && (reft > hc4->base) && (startt[-1] == reft[-1])) {startt--; reft--;} + + if ((ipt-startt) > longest) + { + longest = (int)(ipt-startt); + *matchpos = reft; + *startpos = startt; + } + } + ref = GETNEXT(ref); + } + + return longest; +} + + +inline static int LZ4_encodeSequence(const BYTE** ip, BYTE** op, const BYTE** anchor, int ml, const BYTE* ref) +{ + int length, len; + BYTE* token; + + // Encode Literal length + length = (int)(*ip - *anchor); + token = (*op)++; + if (length>=(int)RUN_MASK) { *token=(RUN_MASK< 254 ; len-=255) *(*op)++ = 255; *(*op)++ = (BYTE)len; } + else *token = (length<=(int)ML_MASK) { *token+=ML_MASK; len-=ML_MASK; for(; len > 509 ; len-=510) { *(*op)++ = 255; *(*op)++ = 255; } if (len > 254) { len-=255; *(*op)++ = 255; } *(*op)++ = (BYTE)len; } + else *token += len; + + // Prepare next loop + *ip += ml; + *anchor = *ip; + + return 0; +} + + +//**************************** +// Compression CODE +//**************************** + +int LZ4_compressHCCtx(LZ4HC_Data_Structure* ctx, + const char* source, + char* dest, + int isize) +{ + const BYTE* ip = (const BYTE*) source; + const BYTE* anchor = ip; + const BYTE* const iend = ip + isize; + const BYTE* const mflimit = iend - MFLIMIT; + const BYTE* const matchlimit = (iend - LASTLITERALS); + + BYTE* op = (BYTE*) dest; + + int ml, ml2, ml3, ml0; + const BYTE* ref=NULL; + const BYTE* start2=NULL; + const BYTE* ref2=NULL; + const BYTE* start3=NULL; + const BYTE* ref3=NULL; + const BYTE* start0; + const BYTE* ref0; + + ip++; + + // Main Loop + while (ip < mflimit) + { + ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref)); + if (!ml) { ip++; continue; } + + // saved, in case we would skip too much + start0 = ip; + ref0 = ref; + ml0 = ml; + +_Search2: + if (ip+ml < mflimit) + ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2); + else ml2=ml; + + if (ml2 == ml) // No better match + { + LZ4_encodeSequence(&ip, &op, &anchor, ml, ref); + continue; + } + + if (start0 < ip) + { + if (start2 < ip + ml0) // empirical + { + ip = start0; + ref = ref0; + ml = ml0; + } + } + + // Here, start0==ip + if ((start2 - ip) < 3) // First Match too small : removed + { + ml = ml2; + ip = start2; + ref =ref2; + goto _Search2; + } + +_Search3: + // Currently we have : + // ml2 > ml1, and + // ip1+3 <= ip2 (usually < ip1+ml1) + if ((start2 - ip) < OPTIMAL_ML) + { + int correction; + int new_ml = ml; + if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML; + if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH; + correction = new_ml - (int)(start2 - ip); + if (correction > 0) + { + start2 += correction; + ref2 += correction; + ml2 -= correction; + } + } + // Now, we have start2 = ip+new_ml, with new_ml=min(ml, OPTIMAL_ML=18) + + if (start2 + ml2 < mflimit) + ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3); + else ml3=ml2; + + if (ml3 == ml2) // No better match : 2 sequences to encode + { + // ip & ref are known; Now for ml + if (start2 < ip+ml) + { + if ((start2 - ip) < OPTIMAL_ML) + { + int correction; + if (ml > OPTIMAL_ML) ml = OPTIMAL_ML; + if (ip+ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH; + correction = ml - (int)(start2 - ip); + if (correction > 0) + { + start2 += correction; + ref2 += correction; + ml2 -= correction; + } + } + else + { + ml = (int)(start2 - ip); + } + } + // Now, encode 2 sequences + LZ4_encodeSequence(&ip, &op, &anchor, ml, ref); + ip = start2; + LZ4_encodeSequence(&ip, &op, &anchor, ml2, ref2); + continue; + } + + if (start3 < ip+ml+3) // Not enough space for match 2 : remove it + { + if (start3 >= (ip+ml)) // can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 + { + if (start2 < ip+ml) + { + int correction = (int)(ip+ml - start2); + start2 += correction; + ref2 += correction; + ml2 -= correction; + if (ml2 < MINMATCH) + { + start2 = start3; + ref2 = ref3; + ml2 = ml3; + } + } + + LZ4_encodeSequence(&ip, &op, &anchor, ml, ref); + ip = start3; + ref = ref3; + ml = ml3; + + start0 = start2; + ref0 = ref2; + ml0 = ml2; + goto _Search2; + } + + start2 = start3; + ref2 = ref3; + ml2 = ml3; + goto _Search3; + } + + // OK, now we have 3 ascending matches; let's write at least the first one + // ip & ref are known; Now for ml + if (start2 < ip+ml) + { + if ((start2 - ip) < (int)ML_MASK) + { + int correction; + if (ml > OPTIMAL_ML) ml = OPTIMAL_ML; + if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH; + correction = ml - (int)(start2 - ip); + if (correction > 0) + { + start2 += correction; + ref2 += correction; + ml2 -= correction; + } + } + else + { + ml = (int)(start2 - ip); + } + } + LZ4_encodeSequence(&ip, &op, &anchor, ml, ref); + + ip = start2; + ref = ref2; + ml = ml2; + + start2 = start3; + ref2 = ref3; + ml2 = ml3; + + goto _Search3; + + } + + // Encode Last Literals + { + int lastRun = (int)(iend - anchor); + if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK< 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; } + else *op++ = (lastRun< #include +#include + #include "eet_suite.h" -static char* +static char * _eet_str_direct_alloc(const char *str) { - return (char*) str; -} + return (char *)str; +} /* _eet_str_direct_alloc */ static void _eet_str_direct_free(const char *str) { -} - -/* Internal list stuff. */ -struct _Eet_List -{ - Eet_List *next; - const void *data; -}; -Eet_List* -eet_list_prepend(Eet_List *list, const void *data) -{ - Eet_List *new; - - new = malloc(sizeof (Eet_List)); - if (!new) return list; - - new->next = list; - new->data = data; - - return new; -} -Eet_List* -eet_list_next(Eet_List *list) -{ - if (!list) return NULL; - - return list->next; -} -void* -eet_list_data(Eet_List *list) -{ - if (!list) return NULL; - - return (void*) list->data; -} -void -eet_list_free(Eet_List *list) -{ - while (list) - { - Eet_List *current = list; - - list = list->next; - free(current); - } -} - -/* Internal hash stuff */ -struct _Eet_Hash -{ - Eet_List *bucket[256]; -}; -typedef struct _Eet_Hash_Item Eet_Hash_Item; -struct _Eet_Hash_Item -{ - const void *data; - char *key; -}; -static inline int -_eet_hash_gen(const char *key) -{ - unsigned int hash_num = 5381; - const unsigned char *ptr; + /* FIXME: Use attribute unused */ + (void)str; +} /* _eet_str_direct_free */ - if (!key) return 0; - for (ptr = (unsigned char *)key; *ptr; ptr++) - hash_num = (hash_num * 33) ^ *ptr; - - hash_num &= 0xff; - return (int)hash_num; -} -void -eet_hash_foreach(const Eet_Hash *hash, int (*func) (const Eet_Hash *hash, const char *key, void *data, void *fdata), const void *fdata) +static void +_eet_eina_hash_foreach(void *hash, + Eina_Hash_Foreach cb, + void *fdata) { - int i; - - if (!hash) return ; - - for (i = 0; i < 256; ++i) - { - Eet_List *over; - - for (over = hash->bucket[i]; over; over = eet_list_next(over)) - { - Eet_Hash_Item *item = eet_list_data(over); - - if (!func(hash, item->key, (void*) item->data, (void*) fdata)) return ; - } - } -} -Eet_Hash* -eet_hash_add(Eet_Hash *hash, const char *key, const void *data) + if (hash) + eina_hash_foreach(hash, cb, fdata); +} /* _eet_eina_hash_foreach */ + +/* Internal wrapper for eina_hash */ +static Eina_Hash * +_eet_eina_hash_add(Eina_Hash *hash, + const char *key, + const void *data) { - Eet_Hash_Item *item; - Eet_List *find; - int index; - - if (!hash) hash = calloc(1, sizeof (Eet_Hash)); - if (!hash) return NULL; - - item = malloc(sizeof (Eet_Hash_Item) + strlen(key) + 1); - if (!item) return hash; + if (!hash) + hash = eina_hash_string_superfast_new(NULL); - item->data = data; - item->key = (char*)(item + 1); - strcpy(item->key, key); - - hash->bucket[_eet_hash_gen(key)] = eet_list_prepend(hash->bucket[_eet_hash_gen(key)], item); + if (!hash) + return NULL; + eina_hash_add(hash, key, data); return hash; -} -void -eet_hash_free(Eet_Hash *hash) -{ - int i; - - if (!hash) return ; +} /* _eet_eina_hash_add */ - for (i = 0; i < 256; ++i) - { - Eet_List *over; - - for (over = hash->bucket[i]; over; over = eet_list_next(over)) - free(eet_list_data(over)); - eet_list_free(hash->bucket[i]); - } - - free(hash); -} +static void +_eet_eina_hash_free(Eina_Hash *hash) +{ + if (hash) + eina_hash_free(hash); +} /* _eet_eina_hash_free */ void eet_test_setup_eddc(Eet_Data_Descriptor_Class *eddc) @@ -150,14 +58,16 @@ eet_test_setup_eddc(Eet_Data_Descriptor_Class *eddc) eddc->func.mem_free = NULL; eddc->func.str_alloc = NULL; eddc->func.str_free = NULL; - eddc->func.list_next = eet_list_next; - eddc->func.list_append = eet_list_prepend; - eddc->func.list_data = eet_list_data; - eddc->func.list_free = eet_list_free; - eddc->func.hash_foreach = eet_hash_foreach; - eddc->func.hash_add = eet_hash_add; - eddc->func.hash_free = eet_hash_free; - eddc->func.str_direct_alloc = _eet_str_direct_alloc; - eddc->func.str_direct_free = _eet_str_direct_free; -} + eddc->func.list_next = (void *)eina_list_next; + eddc->func.list_append = (void *)eina_list_append; + eddc->func.list_data = (void *)eina_list_data_get; + eddc->func.list_free = (void *)eina_list_free; + eddc->func.hash_foreach = (void *)_eet_eina_hash_foreach; + eddc->func.hash_add = (void *)_eet_eina_hash_add; + eddc->func.hash_free = (void *)_eet_eina_hash_free; + eddc->func.str_direct_alloc = (void *)_eet_str_direct_alloc; + eddc->func.str_direct_free = (void *)_eet_str_direct_free; + eddc->func.array_alloc = NULL; + eddc->func.array_free = NULL; +} /* eet_test_setup_eddc */ diff --git a/src/tests/eet_suite.c b/src/tests/eet_suite.c index 003dfa5..91ef2a7 100644 --- a/src/tests/eet_suite.c +++ b/src/tests/eet_suite.c @@ -1,12 +1,31 @@ +#ifdef HAVE_CONFIG_H +# include +#endif /* ifdef HAVE_CONFIG_H */ + +#include +#include #include #include #include #include +#include +#include + +#include + +#ifdef EINA_HAVE_THREADS +#if ((!defined(_WIN32_WCE)) && (!defined(_WIN32))) +# include +# define _EET_INCLUDED_PTHREAD +#endif +#endif /* ifdef EINA_HAVE_THREADS */ #include #include "eet_suite.h" +#define CERT_DIR ((*TESTS_SRC_DIR == '/') ? TESTS_SRC_DIR : "src/tests/" TESTS_SRC_DIR) + START_TEST(eet_test_init) { int ret; @@ -22,39 +41,39 @@ END_TEST typedef struct _Eet_Test_Basic_Type Eet_Test_Basic_Type; struct _Eet_Test_Basic_Type { - char c; - short s; - int i; - long long l; - char *str; - char *istr; - float f1; - float f2; - double d; - unsigned char uc; - unsigned short us; - unsigned int ui; - unsigned long long ul; + char c; + short s; + int i; + long long l; + char *str; + char *istr; + float f1; + float f2; + double d; + unsigned char uc; + unsigned short us; + unsigned int ui; + unsigned long long ul; Eet_Test_Basic_Type *empty; Eet_Test_Basic_Type *with; }; -#define EET_TEST_CHAR 0x42 -#define EET_TEST_SHORT 0x4224 -#define EET_TEST_INT 0x42211224 -#define EET_TEST_LONG_LONG 0x84CB42211224BC48 -#define EET_TEST_STRING "my little test with escape \\\"" -#define EET_TEST_KEY1 "key1" -#define EET_TEST_KEY2 "key2" -#define EET_TEST_FLOAT 123.45689 -#define EET_TEST_FLOAT2 1.0 -#define EET_TEST_FLOAT3 0.25 -#define EET_TEST_FLOAT4 0.0001234 -#define EET_TEST_DOUBLE 123456789.9876543210 -#define EET_TEST_DOUBLE2 1.0 -#define EET_TEST_DOUBLE3 0.25 -#define EET_TEST_FILE_KEY1 "keys/data/1" -#define EET_TEST_FILE_KEY2 "keys/data/2" +#define EET_TEST_CHAR 0x42 +#define EET_TEST_SHORT 0x4224 +#define EET_TEST_INT 0x42211224 +#define EET_TEST_LONG_LONG 0x84CB42211224BC48 +#define EET_TEST_STRING "my little test with escape \\\"" +#define EET_TEST_KEY1 "key1" +#define EET_TEST_KEY2 "key2" +#define EET_TEST_FLOAT 123.45689 +#define EET_TEST_FLOAT2 1.0 +#define EET_TEST_FLOAT3 0.25 +#define EET_TEST_FLOAT4 0.0001234 +#define EET_TEST_DOUBLE 123456789.9876543210 +#define EET_TEST_DOUBLE2 1.0 +#define EET_TEST_DOUBLE3 0.25 +#define EET_TEST_FILE_KEY1 "keys/data/1" +#define EET_TEST_FILE_KEY2 "keys/data/2" #define EET_TEST_FILE_IMAGE "keys/images/" typedef struct _Eet_Test_Image Eet_Test_Image; @@ -62,40 +81,57 @@ struct _Eet_Test_Image { unsigned int w; unsigned int h; - unsigned int alpha; - unsigned int color[]; + int alpha; + unsigned int color[64]; }; static const Eet_Test_Image test_noalpha = { - 8, 8, 0, - { - 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, - 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, - 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, - 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, - 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, - 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, - 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, - 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA - } + 8, 8, 0, + { + 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, + 0x000000AA, 0x00110000, + 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, + 0x00110000, 0x00AA0000, + 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, + 0x00AA0000, 0x0000AA00, + 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, + 0x0000AA00, 0x000000AA, + 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, + 0x000000AA, 0x00110000, + 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, + 0x00110000, 0x00AA0000, + 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, + 0x00AA0000, 0x0000AA00, + 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, + 0x0000AA00, 0x000000AA + } }; static const Eet_Test_Image test_alpha = { - 8, 8, 1, - { - 0x0FAA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x0F110000, - 0x0000AA00, 0x0F0000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x0F110000, 0x00AA0000, - 0x000000AA, 0x00110000, 0x0FAA0000, 0x0000AA00, 0x000000AA, 0x0F110000, 0x00AA0000, 0x0000AA00, - 0x00110000, 0x00AA0000, 0x0000AA00, 0x0F0000AA, 0x0F110000, 0x00AA0000, 0x0000AA00, 0x000000AA, - 0x00AA0000, 0x0000AA00, 0x000000AA, 0x0F110000, 0x0FAA0000, 0x0000AA00, 0x000000AA, 0x00110000, - 0x0000AA00, 0x000000AA, 0x0F110000, 0x00AA0000, 0x0000AA00, 0x0F0000AA, 0x00110000, 0x00AA0000, - 0x000000AA, 0x0F110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x0FAA0000, 0x0000AA00, - 0x0F110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x0F0000AA - } + 8, 8, 1, + { + 0x0FAA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, 0x0000AA00, + 0x000000AA, 0x0F110000, + 0x0000AA00, 0x0F0000AA, 0x00110000, 0x00AA0000, 0x0000AA00, 0x000000AA, + 0x0F110000, 0x00AA0000, + 0x000000AA, 0x00110000, 0x0FAA0000, 0x0000AA00, 0x000000AA, 0x0F110000, + 0x00AA0000, 0x0000AA00, + 0x00110000, 0x00AA0000, 0x0000AA00, 0x0F0000AA, 0x0F110000, 0x00AA0000, + 0x0000AA00, 0x000000AA, + 0x00AA0000, 0x0000AA00, 0x000000AA, 0x0F110000, 0x0FAA0000, 0x0000AA00, + 0x000000AA, 0x00110000, + 0x0000AA00, 0x000000AA, 0x0F110000, 0x00AA0000, 0x0000AA00, 0x0F0000AA, + 0x00110000, 0x00AA0000, + 0x000000AA, 0x0F110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, + 0x0FAA0000, 0x0000AA00, + 0x0F110000, 0x00AA0000, 0x0000AA00, 0x000000AA, 0x00110000, 0x00AA0000, + 0x0000AA00, 0x0F0000AA + } }; static void -_eet_test_basic_set(Eet_Test_Basic_Type *res, int i) +_eet_test_basic_set(Eet_Test_Basic_Type *res, + int i) { res->c = EET_TEST_CHAR; res->s = EET_TEST_SHORT; @@ -103,8 +139,8 @@ _eet_test_basic_set(Eet_Test_Basic_Type *res, int i) res->l = EET_TEST_LONG_LONG; res->str = EET_TEST_STRING; res->istr = EET_TEST_STRING; - res->f1 = - EET_TEST_FLOAT; - res->d = - EET_TEST_DOUBLE; + res->f1 = -EET_TEST_FLOAT; + res->d = -EET_TEST_DOUBLE; res->f2 = EET_TEST_FLOAT4; res->uc = EET_TEST_CHAR; res->us = EET_TEST_SHORT; @@ -115,39 +151,40 @@ _eet_test_basic_set(Eet_Test_Basic_Type *res, int i) if (i == 0) { - Eet_Test_Basic_Type *tmp; - - tmp = malloc(sizeof (Eet_Test_Basic_Type)); - fail_if(!tmp); - - res->with = tmp; - tmp->c = EET_TEST_CHAR; - tmp->s = EET_TEST_SHORT; - tmp->i = EET_TEST_INT + i + 1; - tmp->l = EET_TEST_LONG_LONG; - tmp->str = EET_TEST_STRING; - tmp->istr = EET_TEST_STRING; - tmp->f1 = - EET_TEST_FLOAT; - tmp->d = - EET_TEST_DOUBLE; - tmp->f2 = EET_TEST_FLOAT4; - tmp->uc = EET_TEST_CHAR; - tmp->us = EET_TEST_SHORT; - tmp->ui = EET_TEST_INT; - tmp->ul = EET_TEST_LONG_LONG; - tmp->empty = NULL; - tmp->with = NULL; + Eet_Test_Basic_Type *tmp; + + tmp = malloc(sizeof (Eet_Test_Basic_Type)); + fail_if(!tmp); + + res->with = tmp; + tmp->c = EET_TEST_CHAR; + tmp->s = EET_TEST_SHORT; + tmp->i = EET_TEST_INT + i + 1; + tmp->l = EET_TEST_LONG_LONG; + tmp->str = EET_TEST_STRING; + tmp->istr = EET_TEST_STRING; + tmp->f1 = -EET_TEST_FLOAT; + tmp->d = -EET_TEST_DOUBLE; + tmp->f2 = EET_TEST_FLOAT4; + tmp->uc = EET_TEST_CHAR; + tmp->us = EET_TEST_SHORT; + tmp->ui = EET_TEST_INT; + tmp->ul = EET_TEST_LONG_LONG; + tmp->empty = NULL; + tmp->with = NULL; } -} +} /* _eet_test_basic_set */ static void -_eet_test_basic_check(Eet_Test_Basic_Type *result, int i) +_eet_test_basic_check(Eet_Test_Basic_Type *result, + int i) { float tmp; fail_if(result->c != EET_TEST_CHAR); fail_if(result->s != EET_TEST_SHORT); fail_if(result->i != EET_TEST_INT + i); - fail_if(result->l != EET_TEST_LONG_LONG); + fail_if(result->l != (long long)EET_TEST_LONG_LONG); fail_if(strcmp(result->str, EET_TEST_STRING) != 0); fail_if(strcmp(result->istr, EET_TEST_STRING) != 0); fail_if(result->uc != EET_TEST_CHAR); @@ -156,60 +193,118 @@ _eet_test_basic_check(Eet_Test_Basic_Type *result, int i) fail_if(result->ul != EET_TEST_LONG_LONG); tmp = (result->f1 + EET_TEST_FLOAT); - if (tmp < 0) tmp = -tmp; + if (tmp < 0) + tmp = -tmp; + fail_if(tmp > 0.005); tmp = (result->f2 - EET_TEST_FLOAT4); - if (tmp < 0) tmp = -tmp; + if (tmp < 0) + tmp = -tmp; + fail_if(tmp > 0.005); tmp = (result->d + EET_TEST_DOUBLE); - if (tmp < 0) tmp = -tmp; + if (tmp < 0) + tmp = -tmp; + fail_if(tmp > 0.00005); fail_if(result->empty != NULL); if (i == 0) { - Eet_Test_Basic_Type *tmp; - - tmp = result->with; - fail_if(tmp == NULL); - - fail_if(tmp->c != EET_TEST_CHAR); - fail_if(tmp->s != EET_TEST_SHORT); - fail_if(tmp->i != EET_TEST_INT + i + 1); - fail_if(tmp->l != EET_TEST_LONG_LONG); - fail_if(strcmp(tmp->str, EET_TEST_STRING) != 0); - fail_if(strcmp(tmp->istr, EET_TEST_STRING) != 0); - fail_if(tmp->uc != EET_TEST_CHAR); - fail_if(tmp->us != EET_TEST_SHORT); - fail_if(tmp->ui != EET_TEST_INT); - fail_if(tmp->ul != EET_TEST_LONG_LONG); + Eet_Test_Basic_Type *tmp2; + + tmp2 = result->with; + fail_if(tmp2 == NULL); + + fail_if(tmp2->c != EET_TEST_CHAR); + fail_if(tmp2->s != EET_TEST_SHORT); + fail_if(tmp2->i != EET_TEST_INT + i + 1); + fail_if(tmp2->l != (long long)EET_TEST_LONG_LONG); + fail_if(strcmp(tmp2->str, EET_TEST_STRING) != 0); + fail_if(strcmp(tmp2->istr, EET_TEST_STRING) != 0); + fail_if(tmp2->uc != EET_TEST_CHAR); + fail_if(tmp2->us != EET_TEST_SHORT); + fail_if(tmp2->ui != EET_TEST_INT); + fail_if(tmp2->ul != EET_TEST_LONG_LONG); } else fail_if(result->with != NULL); -} +} /* _eet_test_basic_check */ static void _eet_build_basic_descriptor(Eet_Data_Descriptor *edd) { - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "c", c, EET_T_CHAR); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "s", s, EET_T_SHORT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "i", i, EET_T_INT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "l", l, EET_T_LONG_LONG); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "str", str, EET_T_STRING); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "istr", istr, EET_T_INLINED_STRING); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "f1", f1, EET_T_FLOAT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "f2", f2, EET_T_FLOAT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "d", d, EET_T_DOUBLE); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "uc", uc, EET_T_UCHAR); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "us", us, EET_T_USHORT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "ui", ui, EET_T_UINT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Basic_Type, "ul", ul, EET_T_ULONG_LONG); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "c", + c, + EET_T_CHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "s", + s, + EET_T_SHORT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "i", + i, + EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "l", + l, + EET_T_LONG_LONG); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "str", + str, + EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "istr", + istr, + EET_T_INLINED_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "f1", + f1, + EET_T_FLOAT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "f2", + f2, + EET_T_FLOAT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "d", + d, + EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "uc", + uc, + EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "us", + us, + EET_T_USHORT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "ui", + ui, + EET_T_UINT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Basic_Type, + "ul", + ul, + EET_T_ULONG_LONG); EET_DATA_DESCRIPTOR_ADD_SUB(edd, Eet_Test_Basic_Type, "empty", empty, edd); EET_DATA_DESCRIPTOR_ADD_SUB(edd, Eet_Test_Basic_Type, "with", with, edd); -} +} /* _eet_build_basic_descriptor */ START_TEST(eet_test_basic_data_type_encoding_decoding) { @@ -228,7 +323,7 @@ START_TEST(eet_test_basic_data_type_encoding_decoding) eddc.name = "Eet_Test_Basic_Type"; eddc.size = sizeof(Eet_Test_Basic_Type); - edd = eet_data_descriptor2_new(&eddc); + edd = eet_data_descriptor_stream_new(&eddc); fail_if(!edd); _eet_build_basic_descriptor(edd); @@ -253,40 +348,42 @@ END_TEST typedef struct _Eet_Test_Ex_Type Eet_Test_Ex_Type; struct _Eet_Test_Ex_Type { - char c; - short s; - int i; - unsigned long long l; - char *str; - char *istr; - float f1; - float f2; - float f3; - float f4; - double d1; - double d2; - double d3; - double d4; - Eet_List *list; - Eet_Hash *hash; - Eet_List *ilist; - Eet_Hash *ihash; - Eet_Test_Basic_Type sarray1[10]; - unsigned int sarray2[5]; - unsigned int varray1_count; - unsigned int *varray1; - unsigned int varray2_count; + char c; + short s; + int i; + unsigned long long l; + char *str; + char *istr; + float f1; + float f2; + float f3; + float f4; + double d1; + double d2; + double d3; + double d4; + Eina_List *list; + Eina_Hash *hash; + Eina_List *ilist; + Eina_List *slist; + Eina_Hash *ihash; + Eina_Hash *shash; + Eet_Test_Basic_Type sarray1[10]; + unsigned int sarray2[5]; + unsigned int varray1_count; + unsigned int *varray1; + unsigned int varray2_count; Eet_Test_Basic_Type *varray2; - unsigned char uc; - unsigned short us; - unsigned int ui; - unsigned long long ul; + unsigned char uc; + unsigned short us; + unsigned int ui; + unsigned long long ul; + char *charray[10]; }; static int i42 = 42; static int i7 = 7; - static void _eet_build_ex_descriptor(Eet_Data_Descriptor *edd) { @@ -297,54 +394,151 @@ _eet_build_ex_descriptor(Eet_Data_Descriptor *edd) eet_test_setup_eddc(&eddc); eddc.name = "Eet_Test_Basic_Type"; eddc.size = sizeof(Eet_Test_Basic_Type); - eddb = eet_data_descriptor3_new(&eddc); + eddb = eet_data_descriptor_file_new(&eddc); fail_if(!eddb); _eet_build_basic_descriptor(eddb); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "c", c, EET_T_CHAR); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "s", s, EET_T_SHORT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "c", + c, + EET_T_CHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "s", + s, + EET_T_SHORT); EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "i", i, EET_T_INT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "l", l, EET_T_LONG_LONG); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "str", str, EET_T_STRING); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "istr", istr, EET_T_INLINED_STRING); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "f1", f1, EET_T_FLOAT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "f2", f2, EET_T_FLOAT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "f3", f3, EET_T_FLOAT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "f4", f4, EET_T_FLOAT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "d1", d1, EET_T_DOUBLE); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "d2", d2, EET_T_DOUBLE); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "d3", d3, EET_T_DOUBLE); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "d4", d4, EET_T_DOUBLE); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "uc", uc, EET_T_UCHAR); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "us", us, EET_T_USHORT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "ui", ui, EET_T_UINT); - EET_DATA_DESCRIPTOR_ADD_BASIC(edd, Eet_Test_Ex_Type, "ul", ul, EET_T_ULONG_LONG); - EET_DATA_DESCRIPTOR_ADD_ARRAY(edd, Eet_Test_Ex_Type, "sarray1", sarray1, eddb); - EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(edd, Eet_Test_Ex_Type, "varray2", varray2, eddb); - eet_data_descriptor_element_add(edd, "varray1", EET_T_INT, EET_G_VAR_ARRAY, - (char *)(&(etbt.varray1)) - (char *)(&(etbt)), - (char *)(&(etbt.varray1_count)) - (char *)(&(etbt)), /* 0, */NULL, NULL); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "l", + l, + EET_T_LONG_LONG); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "str", + str, + EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "istr", + istr, + EET_T_INLINED_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "f1", + f1, + EET_T_FLOAT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "f2", + f2, + EET_T_FLOAT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "f3", + f3, + EET_T_FLOAT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "f4", + f4, + EET_T_FLOAT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "d1", + d1, + EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "d2", + d2, + EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "d3", + d3, + EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "d4", + d4, + EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "uc", + uc, + EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "us", + us, + EET_T_USHORT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "ui", + ui, + EET_T_UINT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd, + Eet_Test_Ex_Type, + "ul", + ul, + EET_T_ULONG_LONG); + EET_DATA_DESCRIPTOR_ADD_ARRAY(edd, + Eet_Test_Ex_Type, + "sarray1", + sarray1, + eddb); + EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(edd, + Eet_Test_Ex_Type, + "varray2", + varray2, + eddb); + eet_data_descriptor_element_add(edd, + "varray1", + EET_T_INT, + EET_G_VAR_ARRAY, + (char *)(&(etbt.varray1)) - (char *)(&(etbt)), + (char *)(&(etbt.varray1_count)) - + (char *)(&(etbt)), + /* 0, */ NULL, + NULL); eet_data_descriptor_element_add(edd, "sarray2", EET_T_INT, EET_G_ARRAY, - (char *)(&(etbt.sarray2)) - (char *)(&(etbt)), - /* 0, */sizeof(etbt.sarray2)/sizeof(etbt.sarray2[0]), NULL, NULL); + (char *)(&(etbt.sarray2)) - (char *)(&(etbt)), + /* 0, */ sizeof(etbt.sarray2) / + sizeof(etbt.sarray2[0]), NULL, NULL); + eet_data_descriptor_element_add(edd, "charray", EET_T_STRING, EET_G_ARRAY, + (char *)(&(etbt.charray)) - (char *)(&(etbt)), + /* 0, */ sizeof(etbt.charray) / + sizeof(etbt.charray[0]), NULL, NULL); EET_DATA_DESCRIPTOR_ADD_LIST(edd, Eet_Test_Ex_Type, "list", list, edd); EET_DATA_DESCRIPTOR_ADD_HASH(edd, Eet_Test_Ex_Type, "hash", hash, edd); eet_data_descriptor_element_add(edd, "ilist", EET_T_INT, EET_G_LIST, - (char *)(&(etbt.ilist)) - (char *)(&(etbt)), - 0, /* 0, */NULL, NULL); + (char *)(&(etbt.ilist)) - (char *)(&(etbt)), + 0, /* 0, */ NULL, NULL); eet_data_descriptor_element_add(edd, "ihash", EET_T_INT, EET_G_HASH, - (char *)(&(etbt.ihash)) - (char *)(&(etbt)), - 0, /* 0, */NULL, NULL); -} - -static Eet_Test_Ex_Type* -_eet_test_ex_set(Eet_Test_Ex_Type *res, int offset) + (char *)(&(etbt.ihash)) - (char *)(&(etbt)), + 0, /* 0, */ NULL, NULL); + eet_data_descriptor_element_add(edd, "slist", EET_T_STRING, EET_G_LIST, + (char *)(&(etbt.slist)) - (char *)(&(etbt)), + 0, /* 0, */ NULL, NULL); + eet_data_descriptor_element_add(edd, "shash", EET_T_STRING, EET_G_HASH, + (char *)(&(etbt.shash)) - (char *)(&(etbt)), + 0, /* 0, */ NULL, NULL); +} /* _eet_build_ex_descriptor */ + +static Eet_Test_Ex_Type * +_eet_test_ex_set(Eet_Test_Ex_Type *res, + int offset) { - int i; + unsigned int i; - if (!res) res = malloc( sizeof(Eet_Test_Ex_Type)); - if (!res) return NULL; + if (!res) + res = malloc(sizeof(Eet_Test_Ex_Type)); + + if (!res) + return NULL; res->c = EET_TEST_CHAR + offset; res->s = EET_TEST_SHORT + offset; @@ -364,20 +558,24 @@ _eet_test_ex_set(Eet_Test_Ex_Type *res, int offset) res->hash = NULL; res->ilist = NULL; res->ihash = NULL; + res->slist = NULL; + res->shash = NULL; + for (i = 0; i < sizeof(res->charray) / sizeof(res->charray[0]); ++i) + res->charray[i] = NULL; res->varray2 = malloc(sizeof (Eet_Test_Basic_Type) * 10); res->varray1 = malloc(sizeof (int) * 5); fail_if(!res->varray1 || !res->varray2); for (i = 0; i < 10; ++i) { - _eet_test_basic_set(res->sarray1 + i, i); - _eet_test_basic_set(res->varray2 + i, i); + _eet_test_basic_set(res->sarray1 + i, i); + _eet_test_basic_set(res->varray2 + i, i); } res->varray2_count = 10; for (i = 0; i < 5; ++i) { - res->sarray2[i] = i * 42 + 1; - res->varray1[i] = i * 42 + 1; + res->sarray2[i] = i * 42 + 1; + res->varray1[i] = i * 42 + 1; } res->varray1_count = 5; @@ -387,85 +585,140 @@ _eet_test_ex_set(Eet_Test_Ex_Type *res, int offset) res->ul = EET_TEST_LONG_LONG + offset; return res; -} +} /* _eet_test_ex_set */ static int -_eet_test_ex_check(Eet_Test_Ex_Type *stuff, int offset) +_eet_test_ex_check(Eet_Test_Ex_Type *stuff, + int offset) { double tmp; - int i; + unsigned int i; + + if (!stuff) + return 1; + + if (stuff->c != EET_TEST_CHAR + offset) + return 1; + + if (stuff->s != EET_TEST_SHORT + offset) + return 1; + + if (stuff->i != EET_TEST_INT + offset) + return 1; + + if (stuff->l != EET_TEST_LONG_LONG + offset) + return 1; - if (!stuff) return 1; + if (strcmp(stuff->str, EET_TEST_STRING) != 0) + return 1; - if (stuff->c != EET_TEST_CHAR + offset) return 1; - if (stuff->s != EET_TEST_SHORT + offset) return 1; - if (stuff->i != EET_TEST_INT + offset) return 1; - if (stuff->l != EET_TEST_LONG_LONG + offset) return 1; - if (strcmp(stuff->str, EET_TEST_STRING) != 0) return 1; - if (strcmp(stuff->istr, EET_TEST_STRING) != 0) return 1; + if (strcmp(stuff->istr, EET_TEST_STRING) != 0) + return 1; tmp = stuff->f1 - (EET_TEST_FLOAT + offset); - if (tmp < 0) tmp = -tmp; - if (tmp > 0.005) return 1; + if (tmp < 0) + tmp = -tmp; + + if (tmp > 0.005) + return 1; tmp = stuff->d1 - (EET_TEST_DOUBLE + offset); - if (tmp < 0) tmp = -tmp; - if (tmp > 0.00005) return 1; + if (tmp < 0) + tmp = -tmp; + + if (tmp > 0.00005) + return 1; + + if (stuff->f2 != -(EET_TEST_FLOAT2 + offset)) + return 1; + + if (stuff->d2 != -(EET_TEST_DOUBLE2 + offset)) + return 1; + + if (stuff->f3 != EET_TEST_FLOAT3 + offset) + return 1; + + if (stuff->d3 != EET_TEST_DOUBLE3 + offset) + return 1; + + if (stuff->f4 != EET_TEST_FLOAT2 + offset) + return 1; + + if (stuff->d4 != EET_TEST_DOUBLE2 + offset) + return 1; - if (stuff->f2 != - (EET_TEST_FLOAT2 + offset)) return 1; - if (stuff->d2 != - (EET_TEST_DOUBLE2 + offset)) return 1; + if (stuff->uc != EET_TEST_CHAR + offset) + return 1; - if (stuff->f3 != EET_TEST_FLOAT3 + offset) return 1; - if (stuff->d3 != EET_TEST_DOUBLE3 + offset) return 1; + if (stuff->us != EET_TEST_SHORT + offset) + return 1; - if (stuff->f4 != EET_TEST_FLOAT2 + offset) return 1; - if (stuff->d4 != EET_TEST_DOUBLE2 + offset) return 1; + if (stuff->ui != (unsigned int)EET_TEST_INT + offset) + return 1; - if (stuff->uc != EET_TEST_CHAR + offset) return 1; - if (stuff->us != EET_TEST_SHORT + offset) return 1; - if (stuff->ui != EET_TEST_INT + offset) return 1; - if (stuff->ul != EET_TEST_LONG_LONG + offset) return 1; + if (stuff->ul != EET_TEST_LONG_LONG + offset) + return 1; + + if (stuff->varray1_count != 5) + return 1; + + if (stuff->varray2_count != 10) + return 1; for (i = 0; i < 5; ++i) - if (stuff->sarray2[i] != i * 42 + 1) + if (stuff->sarray2[i] != i * 42 + 1 && stuff->varray1[i] != i * 42 + 1) return 1; for (i = 0; i < 10; ++i) - _eet_test_basic_check(stuff->sarray1 + i, i); + { + _eet_test_basic_check(stuff->sarray1 + i, i); + _eet_test_basic_check(stuff->varray2 + i, i); + } return 0; -} +} /* _eet_test_ex_check */ -static int -func(const Eet_Hash *hash, const char *key, void *data, void *fdata) +static Eina_Bool +func(__UNUSED__ const Eina_Hash *hash, + const void *key, + void *data, + void *fdata) { int *res = fdata; if (strcmp(key, EET_TEST_KEY1) != 0 - && strcmp(key, EET_TEST_KEY2) != 0) *res = 1; - if (_eet_test_ex_check(data, 2)) *res = 1; + && strcmp(key, EET_TEST_KEY2) != 0) + *res = 1; - return 1; -} + if (_eet_test_ex_check(data, 2)) + *res = 1; -static int -func7(const Eet_Hash *hash, const char *key, void *data, void *fdata) + return EINA_TRUE; +} /* func */ + +static Eina_Bool +func7(__UNUSED__ const Eina_Hash *hash, + __UNUSED__ const void *key, + void *data, + void *fdata) { int *res = fdata; int *val; val = data; - if (!val) *res = 1; - if (*val != 7) *res = 1; + if (!val) + *res = 1; - return 1; -} + if (*val != 7) + *res = 1; + + return EINA_TRUE; +} /* func7 */ START_TEST(eet_test_data_type_encoding_decoding) { Eet_Data_Descriptor *edd; Eet_Test_Ex_Type *result; - Eet_Test_Ex_Type *tmp; void *transfert; Eet_Data_Descriptor_Class eddc; Eet_Test_Ex_Type etbt; @@ -475,16 +728,24 @@ START_TEST(eet_test_data_type_encoding_decoding) eet_init(); _eet_test_ex_set(&etbt, 0); - etbt.list = eet_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); - etbt.hash = eet_hash_add(etbt.hash, EET_TEST_KEY1, _eet_test_ex_set(NULL, 2)); - etbt.ilist = eet_list_prepend(etbt.ilist, &i42); - etbt.ihash = eet_hash_add(etbt.ihash, EET_TEST_KEY1, &i7); + etbt.list = eina_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); + etbt.hash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.hash, EET_TEST_KEY1, _eet_test_ex_set(NULL, 2)); + etbt.ilist = eina_list_prepend(etbt.ilist, &i42); + etbt.ihash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.ihash, EET_TEST_KEY1, &i7); + etbt.slist = eina_list_prepend(NULL, "test"); + etbt.shash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.shash, EET_TEST_KEY1, "test"); + memset(&etbt.charray, 0, sizeof(etbt.charray)); + etbt.charray[0] = "test"; + etbt.charray[5] = "plouf"; eet_test_setup_eddc(&eddc); eddc.name = "Eet_Test_Ex_Type"; eddc.size = sizeof(Eet_Test_Ex_Type); - edd = eet_data_descriptor3_new(&eddc); + edd = eet_data_descriptor_file_new(&eddc); fail_if(!edd); _eet_build_ex_descriptor(edd); @@ -496,14 +757,24 @@ START_TEST(eet_test_data_type_encoding_decoding) fail_if(!result); fail_if(_eet_test_ex_check(result, 0) != 0); - fail_if(_eet_test_ex_check(eet_list_data(result->list), 1) != 0); - fail_if(eet_list_data(result->ilist) == NULL); - fail_if(*((int*)eet_list_data(result->ilist)) != 42); + fail_if(_eet_test_ex_check(eina_list_data_get(result->list), 1) != 0); + fail_if(eina_list_data_get(result->ilist) == NULL); + fail_if(*((int *)eina_list_data_get(result->ilist)) != 42); + fail_if(eina_list_data_get(result->slist) == NULL); + fail_if(strcmp(eina_list_data_get(result->slist), "test") != 0); + fail_if(eina_hash_find(result->shash, EET_TEST_KEY1) == NULL); + fail_if(strcmp(eina_hash_find(result->shash, EET_TEST_KEY1), "test") != 0); + fail_if(strcmp(result->charray[0], "test") != 0); + fail_if(strcmp(result->charray[5], "plouf") != 0); test = 0; - eet_hash_foreach(result->hash, func, &test); + if (result->hash) + eina_hash_foreach(result->hash, func, &test); + fail_if(test != 0); - eet_hash_foreach(result->ihash, func7, &test); + if (result->ihash) + eina_hash_foreach(result->ihash, func7, &test); + fail_if(test != 0); eet_shutdown(); @@ -511,24 +782,25 @@ START_TEST(eet_test_data_type_encoding_decoding) END_TEST static void -append_string(void *data, const char *str) +append_string(void *data, + const char *str) { char **string = data; int length; - if (!data) return ; + if (!data) + return; length = *string ? strlen(*string) : 0; *string = realloc(*string, strlen(str) + length + 1); memcpy((*string) + length, str, strlen(str) + 1); -} +} /* append_string */ START_TEST(eet_test_data_type_dump_undump) { Eet_Data_Descriptor *edd; Eet_Test_Ex_Type *result; - Eet_Test_Ex_Type *tmp; Eet_Data_Descriptor_Class eddc; Eet_Test_Ex_Type etbt; char *transfert1; @@ -539,25 +811,32 @@ START_TEST(eet_test_data_type_dump_undump) int size2; int test; - int i; - eet_init(); _eet_test_ex_set(&etbt, 0); - etbt.list = eet_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); - etbt.list = eet_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); - etbt.hash = eet_hash_add(etbt.hash, EET_TEST_KEY1, _eet_test_ex_set(NULL, 2)); - etbt.hash = eet_hash_add(etbt.hash, EET_TEST_KEY2, _eet_test_ex_set(NULL, 2)); - etbt.ilist = eet_list_prepend(etbt.ilist, &i42); - etbt.ilist = eet_list_prepend(etbt.ilist, &i42); - etbt.ihash = eet_hash_add(etbt.ihash, EET_TEST_KEY1, &i7); - etbt.ihash = eet_hash_add(etbt.ihash, EET_TEST_KEY2, &i7); + etbt.list = eina_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); + etbt.list = eina_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); + etbt.hash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.hash, EET_TEST_KEY1, _eet_test_ex_set(NULL, 2)); + etbt.hash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.hash, EET_TEST_KEY2, _eet_test_ex_set(NULL, 2)); + etbt.ilist = eina_list_prepend(etbt.ilist, &i42); + etbt.ilist = eina_list_prepend(etbt.ilist, &i42); + etbt.ihash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.ihash, EET_TEST_KEY1, &i7); + etbt.ihash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.ihash, EET_TEST_KEY2, &i7); + etbt.slist = eina_list_prepend(NULL, "test"); + etbt.shash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.shash, EET_TEST_KEY1, "test"); + memset(&etbt.charray, 0, sizeof(etbt.charray)); + etbt.charray[0] = "test"; eet_test_setup_eddc(&eddc); eddc.name = "Eet_Test_Ex_Type"; eddc.size = sizeof(Eet_Test_Ex_Type); - edd = eet_data_descriptor3_new(&eddc); + edd = eet_data_descriptor_file_new(&eddc); fail_if(!edd); _eet_build_ex_descriptor(edd); @@ -569,34 +848,42 @@ START_TEST(eet_test_data_type_dump_undump) eet_data_text_dump(transfert1, size1, append_string, &string1); fail_if(!string1); - transfert2 = eet_data_text_undump(string1, strlen(string1), &size2); + transfert2 = eet_data_text_undump(string1, string1 ? strlen( + string1) : 0, &size2); fail_if(!transfert2 && size2 <= 0); - fail_if(size1 != size2); string2 = NULL; eet_data_text_dump(transfert2, size2, append_string, &string2); fail_if(!string2); - fail_if(memcmp(transfert1, transfert2, size1) != 0); + fail_if(strlen(string2) != strlen(string1)); result = eet_data_descriptor_decode(edd, transfert2, size2); fail_if(!result); fail_if(_eet_test_ex_check(result, 0) != 0); - fail_if(_eet_test_ex_check(eet_list_data(result->list), 1) != 0); - fail_if(eet_list_data(result->ilist) == NULL); - fail_if(*((int*)eet_list_data(result->ilist)) != 42); + fail_if(_eet_test_ex_check(eina_list_data_get(result->list), 1) != 0); + fail_if(eina_list_data_get(result->ilist) == NULL); + fail_if(*((int *)eina_list_data_get(result->ilist)) != 42); + fail_if(eina_list_data_get(result->slist) == NULL); + fail_if(strcmp(eina_list_data_get(result->slist), "test") != 0); + fail_if(eina_hash_find(result->shash, EET_TEST_KEY1) == NULL); + fail_if(strcmp(eina_hash_find(result->shash, EET_TEST_KEY1), "test") != 0); + fail_if(strcmp(result->charray[0], "test") != 0); test = 0; - eet_hash_foreach(result->hash, func, &test); + if (result->hash) + eina_hash_foreach(result->hash, func, &test); + fail_if(test != 0); - eet_hash_foreach(result->ihash, func7, &test); + if (result->ihash) + eina_hash_foreach(result->ihash, func7, &test); + fail_if(test != 0); eet_shutdown(); } END_TEST - START_TEST(eet_file_simple_write) { const char *buffer = "Here is a string of data to save !"; @@ -607,7 +894,7 @@ START_TEST(eet_file_simple_write) eet_init(); - mktemp(file); + fail_if(!(file = tmpnam(file))); fail_if(eet_mode_get(NULL) != EET_FILE_MODE_INVALID); @@ -615,6 +902,8 @@ START_TEST(eet_file_simple_write) fail_if(!ef); fail_if(!eet_write(ef, "keys/tests", buffer, strlen(buffer) + 1, 1)); + fail_if(!eet_alias(ef, "keys/alias", "keys/tests", 0)); + fail_if(!eet_alias(ef, "keys/alias2", "keys/alias", 1)); fail_if(eet_mode_get(ef) != EET_FILE_MODE_WRITE); @@ -629,12 +918,18 @@ START_TEST(eet_file_simple_write) test = eet_read(ef, "keys/tests", &size); fail_if(!test); - fail_if(size != strlen(buffer) + 1); + fail_if(size != (int)strlen(buffer) + 1); fail_if(memcmp(test, buffer, strlen(buffer) + 1) != 0); + test = eet_read(ef, "keys/alias2", &size); + fail_if(!test); + fail_if(size != (int)strlen(buffer) + 1); + + fail_if(eet_read_direct(ef, "key/alias2", &size)); + fail_if(eet_mode_get(ef) != EET_FILE_MODE_READ); - fail_if(eet_num_entries(ef) != 1); + fail_if(eet_num_entries(ef) != 3); eet_close(ef); @@ -644,7 +939,7 @@ START_TEST(eet_file_simple_write) test = eet_read(ef, "keys/tests", &size); fail_if(!test); - fail_if(size != strlen(buffer) + 1); + fail_if(size != (int)strlen(buffer) + 1); fail_if(memcmp(test, buffer, strlen(buffer) + 1) != 0); @@ -653,54 +948,53 @@ START_TEST(eet_file_simple_write) fail_if(unlink(file) != 0); eet_shutdown(); -} -END_TEST +} /* START_TEST */ +END_TEST START_TEST(eet_file_data_test) { - const char *buffer = "Here is a string of data to save !"; Eet_Data_Descriptor *edd; Eet_Test_Ex_Type *result; - Eet_Test_Ex_Type *tmp; Eet_Dictionary *ed; Eet_File *ef; char **list; - char *transfert1; - char *transfert2; - char *string1; - char *string2; char *file = strdup("/tmp/eet_suite_testXXXXXX"); Eet_Data_Descriptor_Class eddc; Eet_Test_Ex_Type etbt; int size; - int size1; - int size2; int test; - int i; - eet_init(); _eet_test_ex_set(&etbt, 0); - etbt.list = eet_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); - etbt.list = eet_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); - etbt.hash = eet_hash_add(etbt.hash, EET_TEST_KEY1, _eet_test_ex_set(NULL, 2)); - etbt.hash = eet_hash_add(etbt.hash, EET_TEST_KEY2, _eet_test_ex_set(NULL, 2)); - etbt.ilist = eet_list_prepend(etbt.ilist, &i42); - etbt.ilist = eet_list_prepend(etbt.ilist, &i42); - etbt.ihash = eet_hash_add(etbt.ihash, EET_TEST_KEY1, &i7); - etbt.ihash = eet_hash_add(etbt.ihash, EET_TEST_KEY2, &i7); + etbt.list = eina_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); + etbt.list = eina_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); + etbt.hash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.hash, EET_TEST_KEY1, _eet_test_ex_set(NULL, 2)); + etbt.hash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.hash, EET_TEST_KEY2, _eet_test_ex_set(NULL, 2)); + etbt.ilist = eina_list_prepend(etbt.ilist, &i42); + etbt.ilist = eina_list_prepend(etbt.ilist, &i42); + etbt.ihash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.ihash, EET_TEST_KEY1, &i7); + etbt.ihash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.ihash, EET_TEST_KEY2, &i7); + etbt.slist = eina_list_prepend(NULL, "test"); + etbt.shash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.shash, EET_TEST_KEY1, "test"); + memset(&etbt.charray, 0, sizeof(etbt.charray)); + etbt.charray[0] = "test"; eet_test_setup_eddc(&eddc); eddc.name = "Eet_Test_Ex_Type"; eddc.size = sizeof(Eet_Test_Ex_Type); - edd = eet_data_descriptor3_new(&eddc); + edd = eet_data_descriptor_file_new(&eddc); fail_if(!edd); _eet_build_ex_descriptor(edd); - mktemp(file); + fail_if(!(file = tmpnam(file))); /* Insert an error in etbt. */ etbt.i = 0; @@ -732,13 +1026,19 @@ START_TEST(eet_file_data_test) fail_if(!eet_data_write(ef, edd, EET_TEST_FILE_KEY1, &etbt, 0)); + result = eet_data_read(ef, edd, EET_TEST_FILE_KEY1); + fail_if(!result); + + /* Test the resulting data. */ + fail_if(_eet_test_ex_check(result, 0) != 0); + eet_close(ef); /* Read back the data. */ ef = eet_open(file, EET_FILE_MODE_READ_WRITE); fail_if(!ef); - fail_if(!eet_data_write(ef, edd, EET_TEST_FILE_KEY2, &etbt, 1)); + fail_if(!eet_data_write(ef, edd, EET_TEST_FILE_KEY2, &etbt, 0)); result = eet_data_read(ef, edd, EET_TEST_FILE_KEY1); fail_if(!result); @@ -752,21 +1052,34 @@ START_TEST(eet_file_data_test) /* Test the resulting data. */ fail_if(_eet_test_ex_check(result, 0) != 0); - fail_if(_eet_test_ex_check(eet_list_data(result->list), 1) != 0); - fail_if(eet_list_data(result->ilist) == NULL); - fail_if(*((int*)eet_list_data(result->ilist)) != 42); + fail_if(_eet_test_ex_check(eina_list_data_get(result->list), 1) != 0); + fail_if(eina_list_data_get(result->ilist) == NULL); + fail_if(*((int *)eina_list_data_get(result->ilist)) != 42); + fail_if(eina_list_data_get(result->slist) == NULL); + fail_if(strcmp(eina_list_data_get(result->slist), "test") != 0); + fail_if(eina_hash_find(result->shash, EET_TEST_KEY1) == NULL); + fail_if(strcmp(eina_hash_find(result->shash, EET_TEST_KEY1), "test") != 0); + fail_if(strcmp(result->charray[0], "test") != 0); test = 0; - eet_hash_foreach(result->hash, func, &test); + if (result->hash) + eina_hash_foreach(result->hash, func, &test); + fail_if(test != 0); - eet_hash_foreach(result->ihash, func7, &test); + if (result->ihash) + eina_hash_foreach(result->ihash, func7, &test); + fail_if(test != 0); list = eet_list(ef, "keys/*", &size); fail_if(eet_num_entries(ef) != 2); fail_if(size != 2); - fail_if(!(strcmp(list[0], EET_TEST_FILE_KEY1) == 0 && strcmp(list[1], EET_TEST_FILE_KEY2) == 0) - && !(strcmp(list[0], EET_TEST_FILE_KEY2) == 0 && strcmp(list[1], EET_TEST_FILE_KEY1) == 0)); + fail_if(!(strcmp(list[0], + EET_TEST_FILE_KEY1) == 0 && + strcmp(list[1], EET_TEST_FILE_KEY2) == 0) + && !(strcmp(list[0], + EET_TEST_FILE_KEY2) == 0 && + strcmp(list[1], EET_TEST_FILE_KEY1) == 0)); free(list); fail_if(eet_delete(ef, NULL) != 0); @@ -791,58 +1104,55 @@ START_TEST(eet_file_data_test) fail_if(unlink(file) != 0); eet_shutdown(); -} -END_TEST +} /* START_TEST */ +END_TEST START_TEST(eet_file_data_dump_test) { - const char *buffer = "Here is a string of data to save !"; Eet_Data_Descriptor *edd; Eet_Test_Ex_Type *result; - Eet_Test_Ex_Type *tmp; Eet_Data_Descriptor_Class eddc; Eet_Test_Ex_Type etbt; Eet_File *ef; - char *transfert1; - char *transfert2; char *string1; - char *string2; char *file = strdup("/tmp/eet_suite_testXXXXXX"); - int size; - int size1; - int size2; int test; - int i; - eet_init(); _eet_test_ex_set(&etbt, 0); - etbt.list = eet_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); - etbt.list = eet_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); - etbt.hash = eet_hash_add(etbt.hash, EET_TEST_KEY1, _eet_test_ex_set(NULL, 2)); - etbt.hash = eet_hash_add(etbt.hash, EET_TEST_KEY2, _eet_test_ex_set(NULL, 2)); - etbt.ilist = eet_list_prepend(etbt.ilist, &i42); - etbt.ilist = eet_list_prepend(etbt.ilist, &i42); - etbt.ihash = eet_hash_add(etbt.ihash, EET_TEST_KEY1, &i7); - etbt.ihash = eet_hash_add(etbt.ihash, EET_TEST_KEY2, &i7); - - eet_test_setup_eddc(&eddc); - eddc.name = "Eet_Test_Ex_Type"; - eddc.size = sizeof(Eet_Test_Ex_Type); - - edd = eet_data_descriptor3_new(&eddc); + etbt.list = eina_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); + etbt.list = eina_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); + etbt.hash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.hash, EET_TEST_KEY1, _eet_test_ex_set(NULL, 2)); + eina_hash_add(etbt.hash, EET_TEST_KEY2, _eet_test_ex_set(NULL, 2)); + etbt.ilist = eina_list_prepend(etbt.ilist, &i42); + etbt.ilist = eina_list_prepend(etbt.ilist, &i42); + etbt.ihash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.ihash, EET_TEST_KEY1, &i7); + eina_hash_add(etbt.ihash, EET_TEST_KEY2, &i7); + etbt.slist = eina_list_prepend(NULL, "test"); + etbt.shash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.shash, EET_TEST_KEY1, "test"); + memset(&etbt.charray, 0, sizeof(etbt.charray)); + etbt.charray[0] = "test"; + + eet_eina_file_data_descriptor_class_set(&eddc, sizeof (eddc), + "Eet_Test_Ex_Type", + sizeof(Eet_Test_Ex_Type)); + + edd = eet_data_descriptor_file_new(&eddc); fail_if(!edd); _eet_build_ex_descriptor(edd); - mktemp(file); + fail_if(!(file = tmpnam(file))); /* Save the encoded data in a file. */ ef = eet_open(file, EET_FILE_MODE_WRITE); fail_if(!ef); - fail_if(!eet_data_write(ef, edd, EET_TEST_FILE_KEY1, &etbt, 1)); + fail_if(!eet_data_write(ef, edd, EET_TEST_FILE_KEY1, &etbt, 0)); eet_close(ef); @@ -862,98 +1172,158 @@ START_TEST(eet_file_data_dump_test) fail_if(!ef); result = eet_data_read(ef, edd, EET_TEST_FILE_KEY1); - fail_if(!transfert1); + fail_if(!result); eet_close(ef); /* Test the resulting data. */ fail_if(_eet_test_ex_check(result, 0) != 0); - fail_if(_eet_test_ex_check(eet_list_data(result->list), 1) != 0); - fail_if(eet_list_data(result->ilist) == NULL); - fail_if(*((int*)eet_list_data(result->ilist)) != 42); + fail_if(_eet_test_ex_check(eina_list_data_get(result->list), 1) != 0); + fail_if(eina_list_data_get(result->ilist) == NULL); + fail_if(*((int *)eina_list_data_get(result->ilist)) != 42); + fail_if(eina_list_data_get(result->slist) == NULL); + fail_if(strcmp(eina_list_data_get(result->slist), "test") != 0); + fail_if(eina_hash_find(result->shash, EET_TEST_KEY1) == NULL); + fail_if(strcmp(eina_hash_find(result->shash, EET_TEST_KEY1), "test") != 0); + fail_if(strcmp(result->charray[0], "test") != 0); test = 0; - eet_hash_foreach(result->hash, func, &test); + if (result->hash) + eina_hash_foreach(result->hash, func, &test); + fail_if(test != 0); - eet_hash_foreach(result->ihash, func7, &test); + if (result->ihash) + eina_hash_foreach(result->ihash, func7, &test); + fail_if(test != 0); fail_if(unlink(file) != 0); eet_shutdown(); -} -END_TEST +} /* START_TEST */ +END_TEST START_TEST(eet_image) { Eet_File *ef; char *file = strdup("/tmp/eet_suite_testXXXXXX"); - int *data; + unsigned int *data; int compress; int quality; int result; int lossy; int alpha; - int w; - int h; + unsigned int w; + unsigned int h; + + eet_init(); - mktemp(file); + fail_if(!(file = tmpnam(file))); /* Save the encoded data in a file. */ ef = eet_open(file, EET_FILE_MODE_READ_WRITE); fail_if(!ef); - result = eet_data_image_write(ef, EET_TEST_FILE_IMAGE "0", test_noalpha.color, - test_noalpha.w, test_noalpha.h, test_noalpha.alpha, - 0, 100, 0); + result = eet_data_image_write(ef, + EET_TEST_FILE_IMAGE "0", + test_noalpha.color, + test_noalpha.w, + test_noalpha.h, + test_noalpha.alpha, + 0, + 100, + 0); fail_if(result == 0); - result = eet_data_image_write(ef, EET_TEST_FILE_IMAGE "1", test_noalpha.color, - test_noalpha.w, test_noalpha.h, test_noalpha.alpha, - 5, 100, 0); + result = eet_data_image_write(ef, + EET_TEST_FILE_IMAGE "1", + test_noalpha.color, + test_noalpha.w, + test_noalpha.h, + test_noalpha.alpha, + 5, + 100, + 0); fail_if(result == 0); - result = eet_data_image_write(ef, EET_TEST_FILE_IMAGE "2", test_noalpha.color, - test_noalpha.w, test_noalpha.h, test_noalpha.alpha, - 9, 100, 0); + result = eet_data_image_write(ef, + EET_TEST_FILE_IMAGE "2", + test_noalpha.color, + test_noalpha.w, + test_noalpha.h, + test_noalpha.alpha, + 9, + 100, + 0); fail_if(result == 0); - result = eet_data_image_write(ef, EET_TEST_FILE_IMAGE "3", test_noalpha.color, - test_noalpha.w, test_noalpha.h, test_noalpha.alpha, - 0, 100, 1); + result = eet_data_image_write(ef, + EET_TEST_FILE_IMAGE "3", + test_noalpha.color, + test_noalpha.w, + test_noalpha.h, + test_noalpha.alpha, + 0, + 100, + 1); fail_if(result == 0); - result = eet_data_image_write(ef, EET_TEST_FILE_IMAGE "4", test_noalpha.color, - test_noalpha.w, test_noalpha.h, test_noalpha.alpha, - 0, 60, 1); + result = eet_data_image_write(ef, + EET_TEST_FILE_IMAGE "4", + test_noalpha.color, + test_noalpha.w, + test_noalpha.h, + test_noalpha.alpha, + 0, + 60, + 1); fail_if(result == 0); - result = eet_data_image_write(ef, EET_TEST_FILE_IMAGE "5", test_noalpha.color, - test_noalpha.w, test_noalpha.h, test_noalpha.alpha, - 0, 10, 1); + result = eet_data_image_write(ef, + EET_TEST_FILE_IMAGE "5", + test_noalpha.color, + test_noalpha.w, + test_noalpha.h, + test_noalpha.alpha, + 0, + 10, + 1); fail_if(result == 0); - result = eet_data_image_write(ef, EET_TEST_FILE_IMAGE "6", test_noalpha.color, - test_noalpha.w, test_noalpha.h, test_noalpha.alpha, - 0, 0, 1); + result = eet_data_image_write(ef, + EET_TEST_FILE_IMAGE "6", + test_noalpha.color, + test_noalpha.w, + test_noalpha.h, + test_noalpha.alpha, + 0, + 0, + 1); fail_if(result == 0); result = eet_data_image_write(ef, EET_TEST_FILE_IMAGE "7", test_alpha.color, - test_alpha.w, test_alpha.h, test_alpha.alpha, - 9, 100, 0); + test_alpha.w, test_alpha.h, test_alpha.alpha, + 9, 100, 0); fail_if(result == 0); result = eet_data_image_write(ef, EET_TEST_FILE_IMAGE "8", test_alpha.color, - test_alpha.w, test_alpha.h, test_alpha.alpha, - 0, 80, 1); + test_alpha.w, test_alpha.h, test_alpha.alpha, + 0, 80, 1); fail_if(result == 0); result = eet_data_image_write(ef, EET_TEST_FILE_IMAGE "9", test_alpha.color, - test_alpha.w, test_alpha.h, test_alpha.alpha, - 0, 100, 1); + test_alpha.w, test_alpha.h, test_alpha.alpha, + 0, 100, 1); fail_if(result == 0); - data = eet_data_image_read(ef, EET_TEST_FILE_IMAGE "2", &w, &h, &alpha, &compress, &quality, &lossy); + data = eet_data_image_read(ef, + EET_TEST_FILE_IMAGE "2", + &w, + &h, + &alpha, + &compress, + &quality, + &lossy); fail_if(data == NULL); fail_if(w != test_noalpha.w); fail_if(h != test_noalpha.h); @@ -963,7 +1333,14 @@ START_TEST(eet_image) fail_if(data[0] != test_noalpha.color[0]); free(data); - result = eet_data_image_header_read(ef, EET_TEST_FILE_IMAGE "2", &w, &h, &alpha, &compress, &quality, &lossy); + result = eet_data_image_header_read(ef, + EET_TEST_FILE_IMAGE "2", + &w, + &h, + &alpha, + &compress, + &quality, + &lossy); fail_if(result == 0); fail_if(w != test_noalpha.w); fail_if(h != test_noalpha.h); @@ -977,7 +1354,14 @@ START_TEST(eet_image) ef = eet_open(file, EET_FILE_MODE_READ); fail_if(!ef); - result = eet_data_image_header_read(ef, EET_TEST_FILE_IMAGE "0", &w, &h, &alpha, &compress, &quality, &lossy); + result = eet_data_image_header_read(ef, + EET_TEST_FILE_IMAGE "0", + &w, + &h, + &alpha, + &compress, + &quality, + &lossy); fail_if(result == 0); fail_if(w != test_noalpha.w); fail_if(h != test_noalpha.h); @@ -987,7 +1371,18 @@ START_TEST(eet_image) data = malloc(w * h * 4); fail_if(data == NULL); - result = eet_data_image_read_to_surface(ef, EET_TEST_FILE_IMAGE "0", 4, 4, data, 2, 2, w * 4, &alpha, &compress, &quality, &lossy); + result = eet_data_image_read_to_surface(ef, + EET_TEST_FILE_IMAGE "0", + 4, + 4, + data, + 2, + 2, + w * 4, + &alpha, + &compress, + &quality, + &lossy); fail_if(result != 1); fail_if(alpha != test_noalpha.alpha); fail_if(compress != 0); @@ -998,7 +1393,18 @@ START_TEST(eet_image) data = malloc(w * h * 4); fail_if(data == NULL); - result = eet_data_image_read_to_surface(ef, EET_TEST_FILE_IMAGE "0", 0, 0, data, w, h, w * 4, &alpha, &compress, &quality, &lossy); + result = eet_data_image_read_to_surface(ef, + EET_TEST_FILE_IMAGE "0", + 0, + 0, + data, + w, + h, + w * 4, + &alpha, + &compress, + &quality, + &lossy); fail_if(result != 1); fail_if(alpha != test_noalpha.alpha); fail_if(compress != 0); @@ -1007,7 +1413,14 @@ START_TEST(eet_image) fail_if(data[0] != test_noalpha.color[0]); free(data); - data = eet_data_image_read(ef, EET_TEST_FILE_IMAGE "1", &w, &h, &alpha, &compress, &quality, &lossy); + data = eet_data_image_read(ef, + EET_TEST_FILE_IMAGE "1", + &w, + &h, + &alpha, + &compress, + &quality, + &lossy); fail_if(data == NULL); fail_if(w != test_noalpha.w); fail_if(h != test_noalpha.h); @@ -1018,7 +1431,14 @@ START_TEST(eet_image) fail_if(data[0] != test_noalpha.color[0]); free(data); - data = eet_data_image_read(ef, EET_TEST_FILE_IMAGE "2", &w, &h, &alpha, &compress, &quality, &lossy); + data = eet_data_image_read(ef, + EET_TEST_FILE_IMAGE "2", + &w, + &h, + &alpha, + &compress, + &quality, + &lossy); fail_if(data == NULL); fail_if(w != test_noalpha.w); fail_if(h != test_noalpha.h); @@ -1028,7 +1448,14 @@ START_TEST(eet_image) fail_if(data[0] != test_noalpha.color[0]); free(data); - data = eet_data_image_read(ef, EET_TEST_FILE_IMAGE "3", &w, &h, &alpha, &compress, &quality, &lossy); + data = eet_data_image_read(ef, + EET_TEST_FILE_IMAGE "3", + &w, + &h, + &alpha, + &compress, + &quality, + &lossy); fail_if(data == NULL); fail_if(w != test_noalpha.w); fail_if(h != test_noalpha.h); @@ -1036,7 +1463,14 @@ START_TEST(eet_image) fail_if(lossy != 1); free(data); - data = eet_data_image_read(ef, EET_TEST_FILE_IMAGE "5", &w, &h, &alpha, &compress, &quality, &lossy); + data = eet_data_image_read(ef, + EET_TEST_FILE_IMAGE "5", + &w, + &h, + &alpha, + &compress, + &quality, + &lossy); fail_if(data == NULL); fail_if(w != test_noalpha.w); fail_if(h != test_noalpha.h); @@ -1044,7 +1478,14 @@ START_TEST(eet_image) fail_if(lossy != 1); free(data); - data = eet_data_image_read(ef, EET_TEST_FILE_IMAGE "6", &w, &h, &alpha, &compress, &quality, &lossy); + data = eet_data_image_read(ef, + EET_TEST_FILE_IMAGE "6", + &w, + &h, + &alpha, + &compress, + &quality, + &lossy); fail_if(data == NULL); fail_if(w != test_noalpha.w); fail_if(h != test_noalpha.h); @@ -1052,7 +1493,14 @@ START_TEST(eet_image) fail_if(lossy != 1); free(data); - result = eet_data_image_header_read(ef, EET_TEST_FILE_IMAGE "7", &w, &h, &alpha, &compress, &quality, &lossy); + result = eet_data_image_header_read(ef, + EET_TEST_FILE_IMAGE "7", + &w, + &h, + &alpha, + &compress, + &quality, + &lossy); fail_if(result == 0); fail_if(w != test_alpha.w); fail_if(h != test_alpha.h); @@ -1060,7 +1508,14 @@ START_TEST(eet_image) fail_if(compress != 9); fail_if(lossy != 0); - data = eet_data_image_read(ef, EET_TEST_FILE_IMAGE "7", &w, &h, &alpha, &compress, &quality, &lossy); + data = eet_data_image_read(ef, + EET_TEST_FILE_IMAGE "7", + &w, + &h, + &alpha, + &compress, + &quality, + &lossy); fail_if(data == NULL); fail_if(w != test_alpha.w); fail_if(h != test_alpha.h); @@ -1070,14 +1525,28 @@ START_TEST(eet_image) fail_if(data[0] != test_alpha.color[0]); free(data); - result = eet_data_image_header_read(ef, EET_TEST_FILE_IMAGE "9", &w, &h, &alpha, &compress, &quality, &lossy); + result = eet_data_image_header_read(ef, + EET_TEST_FILE_IMAGE "9", + &w, + &h, + &alpha, + &compress, + &quality, + &lossy); fail_if(result == 0); fail_if(w != test_alpha.w); fail_if(h != test_alpha.h); fail_if(alpha != test_alpha.alpha); fail_if(lossy != 1); - data = eet_data_image_read(ef, EET_TEST_FILE_IMAGE "9", &w, &h, &alpha, &compress, &quality, &lossy); + data = eet_data_image_read(ef, + EET_TEST_FILE_IMAGE "9", + &w, + &h, + &alpha, + &compress, + &quality, + &lossy); fail_if(data == NULL); fail_if(w != test_alpha.w); fail_if(h != test_alpha.h); @@ -1087,8 +1556,11 @@ START_TEST(eet_image) eet_close(ef); + fail_if(unlink(file) != 0); + eet_shutdown(); -} +} /* START_TEST */ + END_TEST #define IM0 0x00112233 @@ -1102,8 +1574,8 @@ START_TEST(eet_small_image) unsigned int image[4]; unsigned int *data; Eet_File *ef; - int w; - int h; + unsigned int w; + unsigned int h; int alpha; int compression; int quality; @@ -1117,7 +1589,7 @@ START_TEST(eet_small_image) eet_init(); - mktemp(file); + fail_if(!(file = tmpnam(file))); ef = eet_open(file, EET_FILE_MODE_WRITE); fail_if(!ef); @@ -1130,11 +1602,20 @@ START_TEST(eet_small_image) ef = eet_open(file, EET_FILE_MODE_READ); fail_if(!ef); - data = (unsigned int*) eet_data_image_read(ef, "/images/test", &w, &h, &alpha, &compression, &quality, &lossy); + data = (unsigned int *)eet_data_image_read(ef, + "/images/test", + &w, + &h, + &alpha, + &compression, + &quality, + &lossy); fail_if(data == NULL); eet_close(ef); + fail_if(unlink(file) != 0); + fail_if(data[0] != IM0); fail_if(data[1] != IM1); fail_if(data[2] != IM2); @@ -1143,53 +1624,1156 @@ START_TEST(eet_small_image) free(data); eet_shutdown(); -} +} /* START_TEST */ + END_TEST +START_TEST(eet_identity_simple) +{ + const char *buffer = "Here is a string of data to save !"; + const void *tmp; + Eet_File *ef; + Eet_Key *k; + FILE *noread; + char *test; + char *file = strdup("/tmp/eet_suite_testXXXXXX"); + int size; + int fd; -Suite * -eet_suite(void) + eet_init(); + + fail_if(!(file = tmpnam(file))); + fail_if(chdir(CERT_DIR)); + fail_if(!(noread = fopen("/dev/null", "w"))); + + /* Sign an eet file. */ + ef = eet_open(file, EET_FILE_MODE_WRITE); + fail_if(!ef); + + fail_if(!eet_write(ef, "keys/tests", buffer, strlen(buffer) + 1, 0)); + + k = eet_identity_open("cert.pem", "key.pem", NULL); + fail_if(!k); + + fail_if(eet_identity_set(ef, k) != EET_ERROR_NONE); + eet_identity_print(k, noread); + + eet_close(ef); + + /* Open a signed file. */ + ef = eet_open(file, EET_FILE_MODE_READ); + fail_if(!ef); + + test = eet_read(ef, "keys/tests", &size); + fail_if(!test); + fail_if(size != (int)strlen(buffer) + 1); + + fail_if(memcmp(test, buffer, strlen(buffer) + 1) != 0); + + tmp = eet_identity_x509(ef, &size); + fail_if(tmp == NULL); + + eet_identity_certificate_print(tmp, size, noread); + + eet_close(ef); + + /* As we are changing file contain in less than 1s, this could get unnoticed + by eet cache system. */ + eet_clearcache(); + + /* Corrupting the file. */ + fd = open(file, O_WRONLY); + fail_if(fd < 0); + + fail_if(lseek(fd, 200, SEEK_SET) != 200); + fail_if(write(fd, "42", 2) != 2); + fail_if(lseek(fd, 50, SEEK_SET) != 50); + fail_if(write(fd, "42", 2) != 2); + fail_if(lseek(fd, 88, SEEK_SET) != 88); + fail_if(write(fd, "42", 2) != 2); + + close(fd); + + /* Attempt to open a modified file. */ + ef = eet_open(file, EET_FILE_MODE_READ); + fail_if(ef); + + fail_if(unlink(file) != 0); + + eet_shutdown(); +} /* START_TEST */ + +END_TEST +START_TEST(eet_identity_open_simple) { - Suite *s; - TCase *tc; + Eet_Key *k = NULL; - s = suite_create("Eet"); + eet_init(); - tc = tcase_create("Eet_Init"); - tcase_add_test(tc, eet_test_init); - suite_add_tcase(s, tc); + fail_if(chdir(CERT_DIR)); - tc = tcase_create("Eet Data Encoding/Decoding"); - tcase_add_test(tc, eet_test_basic_data_type_encoding_decoding); - tcase_add_test(tc, eet_test_data_type_encoding_decoding); - tcase_add_test(tc, eet_test_data_type_dump_undump); - suite_add_tcase(s, tc); + k = eet_identity_open("cert.pem", "key.pem", NULL); + fail_if(!k); - tc = tcase_create("Eet File"); - tcase_add_test(tc, eet_file_simple_write); - tcase_add_test(tc, eet_file_data_test); - tcase_add_test(tc, eet_file_data_dump_test); - suite_add_tcase(s, tc); + if (k) + eet_identity_close(k); - tc = tcase_create("Eet Image"); - tcase_add_test(tc, eet_image); - tcase_add_test(tc, eet_small_image); - suite_add_tcase(s, tc); + eet_shutdown(); +} /* START_TEST */ - return s; -} +END_TEST +START_TEST(eet_identity_open_pkcs8) +{ + Eet_Key *k = NULL; -int -main(void) + eet_init(); + + fail_if(chdir(CERT_DIR)); + + k = eet_identity_open("cert.pem", "key_enc_none.pem", NULL); + fail_if(!k); + + if (k) + eet_identity_close(k); + + eet_shutdown(); +} /* START_TEST */ + +END_TEST + +static int +pass_get(char *pass, + int size, + __UNUSED__ int rwflags, + __UNUSED__ void *u) { - Suite *s; - SRunner *sr; - int failed_count; + memset(pass, 0, size); - s = eet_suite(); - sr = srunner_create(s); - srunner_run_all(sr, CK_NORMAL); - failed_count = srunner_ntests_failed(sr); - srunner_free(sr); + if ((int)strlen("password") > size) + return 0; - return (failed_count == 0) ? EXIT_SUCCESS : EXIT_FAILURE; + snprintf(pass, size, "%s", "password"); + return strlen(pass); +} /* pass_get */ + +static int +badpass_get(char *pass, + int size, + __UNUSED__ int rwflags, + __UNUSED__ void *u) +{ + memset(pass, 0, size); + + if ((int)strlen("bad password") > size) + return 0; + + snprintf(pass, size, "%s", "bad password"); + return strlen(pass); +} /* badpass_get */ + +START_TEST(eet_identity_open_pkcs8_enc) +{ + Eet_Key *k = NULL; + + eet_init(); + + fail_if(chdir(CERT_DIR)); + + k = eet_identity_open("cert.pem", "key_enc.pem", NULL); + fail_if(k); + + if (k) + eet_identity_close(k); + + k = eet_identity_open("cert.pem", "key_enc.pem", &badpass_get); + fail_if(k); + + if (k) + eet_identity_close(k); + + k = eet_identity_open("cert.pem", "key_enc.pem", &pass_get); + fail_if(!k); + + if (k) + eet_identity_close(k); + + eet_shutdown(); } +END_TEST +START_TEST(eet_cipher_decipher_simple) +{ + const char *buffer = "Here is a string of data to save !"; + const char *key = "This is a crypto key"; + const char *key_bad = "This is another crypto key"; + Eet_File *ef; + char *test; + char *file = strdup("/tmp/eet_suite_testXXXXXX"); + int size; + + eet_init(); + + fail_if(!(file = tmpnam(file))); + fail_if(chdir(CERT_DIR)); + + /* Crypt an eet file. */ + ef = eet_open(file, EET_FILE_MODE_WRITE); + fail_if(!ef); + + fail_if(!eet_write_cipher(ef, "keys/tests", buffer, strlen(buffer) + 1, 0, + key)); + + eet_close(ef); + + /* Decrypt an eet file. */ + ef = eet_open(file, EET_FILE_MODE_READ); + fail_if(!ef); + + test = eet_read_cipher(ef, "keys/tests", &size, key); + fail_if(!test); + fail_if(size != (int)strlen(buffer) + 1); + + fail_if(memcmp(test, buffer, strlen(buffer) + 1) != 0); + + eet_close(ef); + + /* Decrypt an eet file. */ + ef = eet_open(file, EET_FILE_MODE_READ); + fail_if(!ef); + + test = eet_read_cipher(ef, "keys/tests", &size, key_bad); + + if (size == (int)strlen(buffer) + 1) + fail_if(memcmp(test, buffer, strlen(buffer) + 1) == 0); + + eet_close(ef); + + fail_if(unlink(file) != 0); + + eet_shutdown(); +} /* START_TEST */ + +END_TEST + +#ifdef EINA_HAVE_THREADS + +static Eina_Bool open_worker_stop; + +# ifdef _EET_INCLUDED_PTHREAD + +static void * +open_close_worker(void *path) +{ + while (!open_worker_stop) + { + Eet_File *ef = eet_open((char const *)path, EET_FILE_MODE_READ); + if (ef == NULL) + pthread_exit("eet_open() failed"); + else + { + Eet_Error err_code = eet_close(ef); + if (err_code != EET_ERROR_NONE) + pthread_exit("eet_close() failed"); + } + } + + pthread_exit(NULL); +} /* open_close_worker */ + +# else /* ifdef _EET_INCLUDED_PTHREAD */ + +static unsigned int __stdcall +open_close_worker(void *path) +{ + while (!open_worker_stop) + { + Eet_File *ef = eet_open((char const *)path, EET_FILE_MODE_READ); + if (ef == NULL) + _endthreadex(-1); + else + { + Eet_Error err_code = eet_close(ef); + if (err_code != EET_ERROR_NONE) + _endthreadex(-2); + } + } + + _endthreadex(0); +} /* open_close_worker */ + +# endif /* ifdef _EET_INCLUDED_PTHREAD */ + +START_TEST(eet_cache_concurrency) +{ + char *file = strdup("/tmp/eet_suite_testXXXXXX"); + const char *buffer = "test data"; + Eet_File *ef; + void *thread_ret; + unsigned int n; +# ifdef _EET_INCLUDED_PTHREAD + pthread_t thread; +# else /* ifdef _EET_INCLUDED_PTHREAD */ + uintptr_t thread; + unsigned int thread_id; + DWORD ret; +# endif /* ifdef _EET_INCLUDED_PTHREAD */ + + eet_init(); + eina_threads_init(); + + /* create a file to test with */ + fail_if(!(file = tmpnam(file))); + ef = eet_open(file, EET_FILE_MODE_WRITE); + fail_if(!ef); + fail_if(!eet_write(ef, "keys/tests", buffer, strlen(buffer) + 1, 0)); + + /* start a thread that repeatedly opens and closes a file */ + open_worker_stop = 0; +# ifdef _EET_INCLUDED_PTHREAD + pthread_create(&thread, NULL, open_close_worker, file); +# else /* ifdef _EET_INCLUDED_PTHREAD */ + thread = _beginthreadex(NULL, 0, open_close_worker, file, 0, &thread_id); +# endif /* ifdef _EET_INCLUDED_PTHREAD */ + /* clear the cache repeatedly in this thread */ + for (n = 0; n < 20000; ++n) + { + eet_clearcache(); + } + + /* join the other thread, and fail if it returned an error message */ + open_worker_stop = 1; +# ifdef _EET_INCLUDED_PTHREAD + fail_if(pthread_join(thread, &thread_ret) != 0); + fail_unless(thread_ret == NULL, (char const *)thread_ret); +# else /* ifdef _EET_INCLUDED_PTHREAD */ + ret = WaitForSingleObject((HANDLE)thread, INFINITE); + fail_if(ret != WAIT_OBJECT_0); + fail_if(GetExitCodeThread((HANDLE)thread, &ret) == FALSE); + fail_if(ret != 0); +# endif /* ifdef _EET_INCLUDED_PTHREAD */ + + fail_if(unlink(file) != 0); + + eina_threads_shutdown(); + eet_shutdown(); +} +END_TEST + +#endif /* EINA_HAVE_THREADS */ + +typedef struct _Eet_Connection_Data Eet_Connection_Data; +struct _Eet_Connection_Data +{ + Eet_Connection *conn; + Eet_Data_Descriptor *edd; + Eina_Bool test; +}; + +static Eina_Bool +_eet_connection_read(const void *eet_data, + size_t size, + void *user_data) +{ + Eet_Connection_Data *dt = user_data; + Eet_Test_Ex_Type *result; + Eet_Node *node; + int test; + + result = eet_data_descriptor_decode(dt->edd, eet_data, size); + node = eet_data_node_decode_cipher(eet_data, NULL, size); + + /* Test the resulting data. */ + fail_if(!node); + fail_if(_eet_test_ex_check(result, 0) != 0); + fail_if(_eet_test_ex_check(eina_list_data_get(result->list), 1) != 0); + fail_if(eina_list_data_get(result->ilist) == NULL); + fail_if(*((int *)eina_list_data_get(result->ilist)) != 42); + fail_if(eina_list_data_get(result->slist) == NULL); + fail_if(strcmp(eina_list_data_get(result->slist), "test") != 0); + fail_if(eina_hash_find(result->shash, EET_TEST_KEY1) == NULL); + fail_if(strcmp(eina_hash_find(result->shash, EET_TEST_KEY1), "test") != 0); + fail_if(strcmp(result->charray[0], "test") != 0); + + test = 0; + if (result->hash) + eina_hash_foreach(result->hash, func, &test); + + fail_if(test != 0); + if (result->ihash) + eina_hash_foreach(result->ihash, func7, &test); + + fail_if(test != 0); + + if (!dt->test) + { + dt->test = EINA_TRUE; + fail_if(!eet_connection_node_send(dt->conn, node, NULL)); + } + + return EINA_TRUE; +} /* _eet_connection_read */ + +static Eina_Bool +_eet_connection_write(const void *data, + size_t size, + void *user_data) +{ + Eet_Connection_Data *dt = user_data; + int still; + + if (!dt->test) + { + int step = size / 3; + + eet_connection_received(dt->conn, data, step); + eet_connection_received(dt->conn, (char *)data + step, step); + size -= 2 * step; + still = eet_connection_received(dt->conn, (char *)data + 2 * step, size); + } + else + still = eet_connection_received(dt->conn, data, size); + + fail_if(still); + + return EINA_TRUE; +} /* _eet_connection_write */ + +START_TEST(eet_connection_check) +{ + Eet_Connection *conn; + Eet_Data_Descriptor *edd; + Eet_Data_Descriptor_Class eddc; + Eet_Connection_Data ecd; + Eet_Test_Ex_Type etbt; + Eina_Bool on_going; + + eet_init(); + + _eet_test_ex_set(&etbt, 0); + etbt.list = eina_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); + etbt.list = eina_list_prepend(etbt.list, _eet_test_ex_set(NULL, 1)); + etbt.hash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.hash, EET_TEST_KEY1, _eet_test_ex_set(NULL, 2)); + eina_hash_add(etbt.hash, EET_TEST_KEY2, _eet_test_ex_set(NULL, 2)); + etbt.ilist = eina_list_prepend(etbt.ilist, &i42); + etbt.ilist = eina_list_prepend(etbt.ilist, &i42); + etbt.ihash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.ihash, EET_TEST_KEY1, &i7); + eina_hash_add(etbt.ihash, EET_TEST_KEY2, &i7); + etbt.slist = eina_list_prepend(NULL, "test"); + etbt.shash = eina_hash_string_superfast_new(NULL); + eina_hash_add(etbt.shash, EET_TEST_KEY1, "test"); + memset(&etbt.charray, 0, sizeof(etbt.charray)); + etbt.charray[0] = "test"; + + eet_eina_file_data_descriptor_class_set(&eddc, sizeof (eddc), + "Eet_Test_Ex_Type", + sizeof(Eet_Test_Ex_Type)); + + edd = eet_data_descriptor_file_new(&eddc); + fail_if(!edd); + + _eet_build_ex_descriptor(edd); + + /* Create a connection. */ + conn = eet_connection_new(_eet_connection_read, _eet_connection_write, &ecd); + fail_if(!conn); + + /* Init context. */ + ecd.test = EINA_FALSE; + ecd.conn = conn; + ecd.edd = edd; + + /* Test the connection. */ + fail_if(!eet_connection_send(conn, edd, &etbt, NULL)); + + fail_if(!ecd.test); + + fail_if(!eet_connection_close(conn, &on_going)); + + fail_if(on_going); + + eet_shutdown(); +} +END_TEST + +struct _Eet_5FP +{ + Eina_F32p32 fp32; + Eina_F16p16 fp16; + Eina_F8p24 fp8; + Eina_F32p32 f1; + Eina_F32p32 f0; +}; +typedef struct _Eet_5FP Eet_5FP; + +struct _Eet_5DBL +{ + double fp32; + double fp16; + float fp8; + double f1; + double f0; +}; +typedef struct _Eet_5DBL Eet_5DBL; + +START_TEST(eet_fp) +{ + Eet_Data_Descriptor_Class eddc; + Eet_Data_Descriptor *edd_5FP; + Eet_Data_Descriptor *edd_5DBL; + Eet_5FP origin; + Eet_5DBL *convert; + Eet_5FP *build; + void *blob; + int size; + + eet_init(); + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_5FP); + edd_5FP = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "fp32", fp32, EET_T_F32P32); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "fp16", fp16, EET_T_F16P16); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "fp8", fp8, EET_T_F8P24); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f1", f1, EET_T_F32P32); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f0", f0, EET_T_F32P32); + + eet_eina_stream_data_descriptor_class_set(&eddc, sizeof (eddc), "Eet_5FP", sizeof (Eet_5DBL)); + edd_5DBL = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp32", fp32, EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp16", fp16, EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp8", fp8, EET_T_FLOAT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "f1", f1, EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "f0", f0, EET_T_DOUBLE); + + origin.fp32 = eina_f32p32_double_from(1.125); + origin.fp16 = eina_f16p16_int_from(2000); + origin.fp8 = eina_f8p24_int_from(125); + origin.f1 = eina_f32p32_int_from(1); + origin.f0 = 0; + + blob = eet_data_descriptor_encode(edd_5FP, &origin, &size); + fail_if(!blob || size <= 0); + + build = eet_data_descriptor_decode(edd_5FP, blob, size); + fail_if(!build); + + convert = eet_data_descriptor_decode(edd_5DBL, blob, size); + fail_if(!convert); + + fail_if(build->fp32 != eina_f32p32_double_from(1.125)); + fail_if(build->fp16 != eina_f16p16_int_from(2000)); + fail_if(build->fp8 != eina_f8p24_int_from(125)); + fail_if(build->f1 != eina_f32p32_int_from(1)); + fail_if(build->f0 != 0); + + fail_if(convert->fp32 != 1.125); + fail_if(convert->fp16 != 2000); + fail_if(convert->fp8 != 125); + fail_if(convert->f1 != 1); + fail_if(convert->f0 != 0); + + eet_shutdown(); +} +END_TEST +START_TEST(eet_file_fp) +{ + char *file = strdup("/tmp/eet_suite_testXXXXXX"); + Eet_Data_Descriptor_Class eddc; + Eet_Data_Descriptor *edd_5FP; + Eet_Data_Descriptor *edd_5DBL; + Eet_File *ef; + Eet_5FP origin; + Eet_5DBL *convert; + Eet_5FP *build; + + eet_init(); + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_5FP); + edd_5FP = eet_data_descriptor_file_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "fp32", fp32, EET_T_F32P32); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "fp16", fp16, EET_T_F16P16); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "fp8", fp8, EET_T_F8P24); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f1", f1, EET_T_F32P32); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5FP, Eet_5FP, "f0", f0, EET_T_F32P32); + + eet_eina_file_data_descriptor_class_set(&eddc, sizeof (eddc), "Eet_5FP", sizeof (Eet_5DBL)); + edd_5DBL = eet_data_descriptor_file_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp32", fp32, EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp16", fp16, EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "fp8", fp8, EET_T_FLOAT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "f1", f1, EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_5DBL, Eet_5DBL, "f0", f0, EET_T_DOUBLE); + + origin.fp32 = eina_f32p32_double_from(1.125); + origin.fp16 = eina_f16p16_int_from(2000); + origin.fp8 = eina_f8p24_int_from(125); + origin.f1 = eina_f32p32_int_from(1); + origin.f0 = 0; + + fail_if(!(file = tmpnam(file))); + + ef = eet_open(file, EET_FILE_MODE_READ_WRITE); + fail_if(!ef); + + fail_if(!eet_data_write(ef, edd_5FP, EET_TEST_FILE_KEY1, &origin, 1)); + + build = eet_data_read(ef, edd_5FP, EET_TEST_FILE_KEY1); + fail_if(!build); + + convert = eet_data_read(ef, edd_5DBL, EET_TEST_FILE_KEY1); + fail_if(!convert); + + fail_if(build->fp32 != eina_f32p32_double_from(1.125)); + fail_if(build->fp16 != eina_f16p16_int_from(2000)); + fail_if(build->fp8 != eina_f8p24_int_from(125)); + fail_if(build->f1 != eina_f32p32_int_from(1)); + fail_if(build->f0 != 0); + + fail_if(convert->fp32 != 1.125); + fail_if(convert->fp16 != 2000); + fail_if(convert->fp8 != 125); + fail_if(convert->f1 != 1); + fail_if(convert->f0 != 0); + + eet_close(ef); + + fail_if(unlink(file) != 0); + + eet_shutdown(); +} /* START_TEST */ + +END_TEST + +typedef struct _Eet_Union_Test Eet_Union_Test; +typedef struct _Eet_Variant_Test Eet_Variant_Test; +typedef struct _Eet_Variant_Type Eet_Variant_Type; +typedef struct _Eet_Inherit_Test1 Eet_Inherit_Test1; +typedef struct _Eet_Inherit_Test2 Eet_Inherit_Test2; +typedef struct _Eet_Inherit_Test3 Eet_Inherit_Test3; +typedef struct _Eet_St1 Eet_St1; +typedef struct _Eet_St2 Eet_St2; +typedef struct _Eet_St3 Eet_St3; +typedef struct _Eet_List Eet_List; + +typedef enum _Eet_Union +{ + EET_UNKNOWN, + EET_ST1, + EET_ST2, + EET_ST3 +} Eet_Union; + +struct +{ + Eet_Union u; + const char *name; +} eet_mapping[] = { + { EET_ST1, "ST1" }, + { EET_ST2, "ST2" }, + { EET_ST3, "ST3" }, + { EET_UNKNOWN, NULL } +}; + +struct _Eet_St1 +{ + double val1; + int stuff; + char *s1; +}; + +struct _Eet_St2 +{ + Eina_Bool b1; + unsigned long long v1; +}; + +struct _Eet_St3 +{ + int boby; +}; + +struct _Eet_Union_Test +{ + Eet_Union type; + + union { + Eet_St1 st1; + Eet_St2 st2; + Eet_St3 st3; + } u; +}; + +struct _Eet_Variant_Type +{ + const char *type; + Eina_Bool unknow : 1; +}; + +struct _Eet_Variant_Test +{ + Eet_Variant_Type t; + + void *data; + Eina_List *data_list; +}; + +struct _Eet_Inherit_Test1 +{ + Eet_Union type; + Eet_St1 st1; +}; +struct _Eet_Inherit_Test2 +{ + Eet_Union type; + Eet_St2 st2; +}; +struct _Eet_Inherit_Test3 +{ + Eet_Union type; + Eet_St3 st3; +}; + +struct _Eet_List +{ + Eina_List *list; +}; + +static const char * +_eet_union_type_get(const void *data, + Eina_Bool *unknow) +{ + const Eet_Union *u = data; + int i; + + if (unknow) + *unknow = EINA_FALSE; + + for (i = 0; eet_mapping[i].name != NULL; ++i) + if (*u == eet_mapping[i].u) + return eet_mapping[i].name; + + if (unknow) + *unknow = EINA_TRUE; + + return NULL; +} /* _eet_union_type_get */ + +static Eina_Bool +_eet_union_type_set(const char *type, + void *data, + Eina_Bool unknow) +{ + Eet_Union *u = data; + int i; + + if (unknow) + return EINA_FALSE; + + for (i = 0; eet_mapping[i].name != NULL; ++i) + if (strcmp(eet_mapping[i].name, type) == 0) + { + *u = eet_mapping[i].u; + return EINA_TRUE; + } + + return EINA_FALSE; +} /* _eet_union_type_set */ + +static const char * +_eet_variant_type_get(const void *data, + Eina_Bool *unknow) +{ + const Eet_Variant_Type *type = data; + int i; + + if (unknow) + *unknow = type->unknow; + + for (i = 0; eet_mapping[i].name != NULL; ++i) + if (strcmp(type->type, eet_mapping[i].name) == 0) + return eet_mapping[i].name; + + if (unknow) + *unknow = EINA_FALSE; + + return type->type; +} /* _eet_variant_type_get */ + +static Eina_Bool +_eet_variant_type_set(const char *type, + void *data, + Eina_Bool unknow) +{ + Eet_Variant_Type *vt = data; + + vt->type = type; + vt->unknow = unknow; + return EINA_TRUE; +} /* _eet_variant_type_set */ + +static Eet_Data_Descriptor * +_eet_st1_dd(void) +{ + Eet_Data_Descriptor_Class eddc; + Eet_Data_Descriptor *res; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_St1); + res = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St1, "val1", val1, EET_T_DOUBLE); + EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St1, "stuff", stuff, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St1, "s1", s1, EET_T_STRING); + + return res; +} /* _eet_st1_dd */ + +static void +_eet_st1_set(Eet_St1 *st1, + int i) +{ + st1->val1 = EET_TEST_DOUBLE; + st1->stuff = EET_TEST_INT + i; + st1->s1 = EET_TEST_STRING; +} /* _eet_st1_set */ + +static void +_eet_st1_cmp(Eet_St1 *st1, + int i) +{ + double tmp; + + fail_if(!st1); + + tmp = st1->val1 - EET_TEST_DOUBLE; + if (tmp < 0) + tmp = -tmp; + + fail_if(tmp > 0.005); + fail_if(st1->stuff != EET_TEST_INT + i); + fail_if(strcmp(st1->s1, EET_TEST_STRING)); +} /* _eet_st1_cmp */ + +static Eet_Data_Descriptor * +_eet_st2_dd(void) +{ + Eet_Data_Descriptor_Class eddc; + Eet_Data_Descriptor *res; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_St2); + res = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St2, "b1", b1, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St2, "v1", v1, EET_T_ULONG_LONG); + + return res; +} /* _eet_st2_dd */ + +static void +_eet_st2_set(Eet_St2 *st2, + int i) +{ + st2->b1 = EINA_TRUE; + st2->v1 = EET_TEST_LONG_LONG + i; +} /* _eet_st2_set */ + +static void +_eet_st2_cmp(Eet_St2 *st2, + int i) +{ + fail_if(!st2->b1); + fail_if(st2->v1 != EET_TEST_LONG_LONG + i); +} /* _eet_st2_cmp */ + +static Eet_Data_Descriptor * +_eet_st3_dd(void) +{ + Eet_Data_Descriptor_Class eddc; + Eet_Data_Descriptor *res; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_St3); + res = eet_data_descriptor_stream_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St3, "boby", boby, EET_T_INT); + + return res; +} /* _eet_st3_dd */ + +static void +_eet_st3_set(Eet_St3 *st3, + int i) +{ + st3->boby = EET_TEST_INT + i; +} /* _eet_st3_set */ + +static void +_eet_st3_cmp(Eet_St3 *st3, + int i) +{ + fail_if(st3->boby != EET_TEST_INT + i); +} /* _eet_st3_cmp */ + +START_TEST(eet_test_union) +{ + Eet_Union_Test *eut; + Eet_List *l; + Eet_Data_Descriptor_Class eddc; + Eet_Data_Descriptor *edd; + Eet_Data_Descriptor *unified; + Eet_Data_Descriptor *m; + void *blob; + int size; + int i; + + eina_init(); + eet_init(); + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_Union_Test); + edd = eet_data_descriptor_stream_new(&eddc); + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_Union_Test); + m = eet_data_descriptor_stream_new(&eddc); + + eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION; + eddc.func.type_get = _eet_union_type_get; + eddc.func.type_set = _eet_union_type_set; + unified = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST1", _eet_st1_dd()); + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST2", _eet_st2_dd()); + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST3", _eet_st3_dd()); + + EET_DATA_DESCRIPTOR_ADD_UNION(edd, Eet_Union_Test, "u", u, type, unified); + + EET_DATA_DESCRIPTOR_ADD_LIST(m, Eet_List, "list", list, edd); + + l = calloc(1, sizeof (Eet_List)); + +#define EUT_NEW(Type_Index) \ + eut = calloc(1, sizeof (Eet_Union_Test)); \ + eut->type = EET_ST ## Type_Index; \ + _eet_st ## Type_Index ## _set(&(eut->u.st ## Type_Index), i); + + for (i = 0; i < 3; ++i) + { + EUT_NEW(1); + l->list = eina_list_append(l->list, eut); + + EUT_NEW(2); + l->list = eina_list_append(l->list, eut); + + EUT_NEW(3); + l->list = eina_list_append(l->list, eut); + } + + blob = eet_data_descriptor_encode(m, l, &size); + fail_if(!blob || size <= 0); + + l = eet_data_descriptor_decode(m, blob, size); + fail_if(!l); + + fail_if(eina_list_count(l->list) != 9); + +#define EUT_CMP(Type_Index) \ + eut = eina_list_nth(l->list, i * 3 + Type_Index - 1); \ + fail_if(eut->type != EET_ST ## Type_Index); \ + _eet_st ## Type_Index ## _cmp(&(eut->u.st ## Type_Index), i); + + for (i = 0; i < 3; ++i) + { + EUT_CMP(1); + EUT_CMP(2); + EUT_CMP(3); + } + + eet_shutdown(); + eina_shutdown(); +} +END_TEST +START_TEST(eet_test_variant) +{ + Eet_Variant_Test *evt; + Eet_List *l; + Eet_St1 *st1; + Eet_St2 *st2; + Eet_St3 *st3; + Eet_Data_Descriptor_Class eddc; + Eet_Data_Descriptor *edd; + Eet_Data_Descriptor *unified; + Eet_Data_Descriptor *m; + void *blob; + int size; + int i; + + eina_init(); + eet_init(); + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_Variant_Test); + edd = eet_data_descriptor_stream_new(&eddc); + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_Variant_Test); + m = eet_data_descriptor_stream_new(&eddc); + + eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION; + eddc.func.type_get = _eet_variant_type_get; + eddc.func.type_set = _eet_variant_type_set; + unified = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST1", _eet_st1_dd()); + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST2", _eet_st2_dd()); + EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST3", _eet_st3_dd()); + + EET_DATA_DESCRIPTOR_ADD_VARIANT(edd, + Eet_Variant_Test, + "data", + data, + t, + unified); + + unified = eet_data_descriptor_stream_new(&eddc); + eet_data_descriptor_element_add(unified, "ST1", + EET_T_UNKNOW, EET_G_LIST, + 0, 0, NULL, _eet_st1_dd()); + eet_data_descriptor_element_add(unified, "ST2", + EET_T_UNKNOW, EET_G_LIST, + 0, 0, NULL, _eet_st2_dd()); + + EET_DATA_DESCRIPTOR_ADD_VARIANT(edd, Eet_Variant_Test, + "data_list", data_list, t, unified); + + EET_DATA_DESCRIPTOR_ADD_LIST(m, Eet_List, "list", list, edd); + + l = calloc(1, sizeof (Eet_List)); + +#define EVT_NEW(Type_Index) \ + evt = calloc(1, sizeof (Eet_Variant_Test)); \ + evt->t.type = eet_mapping[Type_Index - 1].name; \ + st ## Type_Index = calloc(1, sizeof (Eet_St ## Type_Index)); \ + _eet_st ## Type_Index ## _set(st ## Type_Index, i); \ + evt->data = st ## Type_Index; + + for (i = 0; i < 3; ++i) + { + EVT_NEW(1); + l->list = eina_list_append(l->list, evt); + + st1 = calloc(1, sizeof (Eet_St1)); + _eet_st1_set(st1, i); + evt->data_list = eina_list_append(evt->data_list, st1); + + EVT_NEW(2); + l->list = eina_list_append(l->list, evt); + + EVT_NEW(3); + l->list = eina_list_append(l->list, evt); + } + + blob = eet_data_descriptor_encode(m, l, &size); + fail_if(!blob || size <= 0); + + l = eet_data_descriptor_decode(m, blob, size); + fail_if(!l); + + fail_if(eina_list_count(l->list) != 9); + +#define EVT_CMP(Type_Index) \ + evt = eina_list_nth(l->list, i * 3 + Type_Index - 1); \ + fail_if(strcmp(evt->t.type, eet_mapping[Type_Index - 1].name) != 0); \ + _eet_st ## Type_Index ## _cmp(evt->data, i); + + for (i = 0; i < 3; ++i) + { + EVT_CMP(1); + + fail_if(!evt->data_list); + fail_if(eina_list_count(evt->data_list) != 1); + + st1 = eina_list_data_get(evt->data_list); + _eet_st1_cmp(st1, i); + + EVT_CMP(2); + EVT_CMP(3); + } + + eet_shutdown(); + eina_shutdown(); +} /* START_TEST */ + +END_TEST + +Suite * +eet_suite(void) +{ + Suite *s; + TCase *tc; + + s = suite_create("Eet"); + + tc = tcase_create("Eet_Init"); + tcase_add_test(tc, eet_test_init); + suite_add_tcase(s, tc); + + tc = tcase_create("Eet Data Encoding/Decoding"); + tcase_add_test(tc, eet_test_basic_data_type_encoding_decoding); + tcase_add_test(tc, eet_test_data_type_encoding_decoding); + tcase_add_test(tc, eet_test_data_type_dump_undump); + tcase_add_test(tc, eet_fp); + tcase_add_test(tc, eet_test_union); + tcase_add_test(tc, eet_test_variant); + suite_add_tcase(s, tc); + + tc = tcase_create("Eet File"); + tcase_add_test(tc, eet_file_simple_write); + tcase_add_test(tc, eet_file_data_test); + tcase_add_test(tc, eet_file_data_dump_test); + tcase_add_test(tc, eet_file_fp); + suite_add_tcase(s, tc); + + tc = tcase_create("Eet Image"); + tcase_add_test(tc, eet_image); + tcase_add_test(tc, eet_small_image); + suite_add_tcase(s, tc); + +#ifdef HAVE_SIGNATURE + tc = tcase_create("Eet Identity"); + tcase_add_test(tc, eet_identity_simple); + tcase_add_test(tc, eet_identity_open_simple); + tcase_add_test(tc, eet_identity_open_pkcs8); + tcase_add_test(tc, eet_identity_open_pkcs8_enc); + suite_add_tcase(s, tc); +#endif /* ifdef HAVE_SIGNATURE */ + +#ifdef HAVE_CIPHER + tc = tcase_create("Eet Cipher"); + tcase_add_test(tc, eet_cipher_decipher_simple); + suite_add_tcase(s, tc); +#endif /* ifdef HAVE_CIPHER */ + +#ifdef EINA_HAVE_THREADS + tc = tcase_create("Eet Cache"); + tcase_add_test(tc, eet_cache_concurrency); + suite_add_tcase(s, tc); +#endif /* ifdef EFL_HAVE_THREADS */ + + tc = tcase_create("Eet Connection"); + tcase_add_test(tc, eet_connection_check); + suite_add_tcase(s, tc); + + return s; +} /* eet_suite */ + +int +main(void) +{ + Suite *s; + SRunner *sr; + int failed_count; + + s = eet_suite(); + sr = srunner_create(s); + srunner_run_all(sr, CK_ENV); + failed_count = srunner_ntests_failed(sr); + srunner_free(sr); + + return (failed_count == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} /* main */ + diff --git a/src/tests/eet_suite.h b/src/tests/eet_suite.h index 4b979a2..c5c91aa 100644 --- a/src/tests/eet_suite.h +++ b/src/tests/eet_suite.h @@ -3,19 +3,7 @@ #include "Eet.h" -typedef struct _Eet_List Eet_List; -typedef struct _Eet_Hash Eet_Hash; - -Eet_List* eet_list_prepend(Eet_List *list, const void *data); -Eet_List* eet_list_next(Eet_List *list); -void* eet_list_data(Eet_List *list); -void eet_list_free(Eet_List *list); - -void eet_hash_foreach(const Eet_Hash *hash, int (*func) (const Eet_Hash *hash, const char *key, void *data, void *fdata), const void *fdata); -Eet_Hash* eet_hash_add(Eet_Hash *hash, const char *key, const void *data); -void eet_hash_free(Eet_Hash *hash); - -void eet_test_setup_eddc(Eet_Data_Descriptor_Class *eddc); - +void +eet_test_setup_eddc(Eet_Data_Descriptor_Class *eddc); #endif /* _EET_SUITE_H */ diff --git a/src/tests/key.pem b/src/tests/key.pem new file mode 100644 index 0000000..74763ca --- /dev/null +++ b/src/tests/key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDIhOPOnkTinjxtP+t/Q+F00w0fV0kVqdcamc6uz/o41kRW2fzF +lSFc5HODEZvN1DqJWz4++i4zNdHLHmlQISuxvQh6dnbq+GpVr3Qlzx+UPizzhUvY +DMdCc/RGXhxzh2Si8iXSkpqLfs5bsCUy3tPNUUVMMzSnLeia1VRv+0piEwIDAQAB +AoGAfLLHyNJ8HEIzae16UmawaqplWrw5YxOABbbo5aXJAledoDVoEKexW8dmXngw +4Eu/K3RmvVtwJ8CsexiqfX5jYMU+YKRbww6Vqr/punIUhiEHVarHMFKG9yo14qSa +z2xPgXvC5p7/Rhci+rAUp36S5kIHch5sLhEEcJayymyzDyECQQD/5B3JdpcovrSI ++nyZ8Iub2+I3f3uox6m1DKxHead26ICoIr7VCnPV5J1gLIB2MofVCbKhmy4PNi5a +0QdvazJfAkEAyJq9Y+9SQ4sCOVDrFklJxhXuZE4WbnR32XsBdnQ9dauo0E2vDVkv +6mHnzMWroTjLv4hH5nufE5NvMo8PNGB0zQJAFOKkf737JmsyRv/Szamxa14t/4Ob +LzJkqo9HPGo0feMKJS74zmCVBb8sDR50ubD0HzI0bzZAMyOj8uuepLxmFwJAH+RR +5bhfeLN52AjgRvvBycckzjeH42mKwD2I/v794l43CV7ATLv4HSgRhQGMBqaT5dBR +tffDU4Zl8EDEJwyKpQJBAJ2NNacURTyavU699QJOIdGAsA4KXici8H3PuuWMtHLR +RKdPFeaCRn+9p7Tglf0rH9hUGOpUXHYD3+ECt6gnVDc= +-----END RSA PRIVATE KEY----- diff --git a/src/tests/key_enc.pem b/src/tests/key_enc.pem new file mode 100644 index 0000000..83c1ba2 --- /dev/null +++ b/src/tests/key_enc.pem @@ -0,0 +1,17 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQILLqDZE1i0Y8CAggA +MBQGCCqGSIb3DQMHBAjwbnSdTCCDOASCAoB0rMuSIXrzqFQnCexMkC9A5jyd+HvC +2UV6EWIfFU4yBvp+2dfHg6RKUoZ0wGk8FxAkaAj+boVwf16PPXXQ70AQBb0iGeb4 +YLdjDF2zSoIK3SbsWrhAfJhSMbcMftEZnLTYxLSkTv5R8jb0IPybVNTqFf+KmGav +DwyRVQrdAxIYdJSPwd61Fhs1VqzptmQ8DLKHy35X1fIro3py4jncBhsuqf6H3yj1 +ZFuzCPnwB8unASgbTPD43yObrjyWTjbTtp59WavVdnNS+m7QNW+OfxznHUUJXtMz +/EniglUhR1Uf75wpMpQIPfC77Cary0Y4iLGQZiF1C0WjQzMBufckJFJVRFGfkkMl +ijlaijLUYMqENJ6wsyK5lihsoBCzIDoqI375s9pdeln8sd33Yu+L/Gu4Xo8Bh5cM +6mlo9WUgw5KibmlZHGEAGdKxcvL0ywswuwQ6yhwcdvCAt6MfrWJNpksa9JmpXJi8 +c21lHwnoyG1DgSqY5VhRyitfnuY3Jegj+7njhooiAJM9w7fxpafN9oxiaJBvPFqd +lfJ42Pj5rkjjVqXOJX7Cf7sF85tW7ygwdGWyXvHn2fhQ+vjaDtZalry//Xytet4r +lvTerO6M6WVMk2yM7vdeBU7c74LVIJmwGR6d837OPax1V+Z9yq6zDuJAQ3l9mtmu +gowV3xInTFRsnSOQcYW5y8dNnugR9FBh8f1NI7SPyW0reeVbPXXhRxg+TyogIXhh +yAfWJ6dDLZ31EVCdqRKxK7b9u2r3dsuaiwT1jFg59Eu2AifFi0j7aDA1lGIKoj3C +cPDwJd8weC+UoWpWX/O4KOpaU62Rwt5wRoOxELG6lHy7cOjZgLmwjg1G +-----END ENCRYPTED PRIVATE KEY----- diff --git a/src/tests/key_enc_none.pem b/src/tests/key_enc_none.pem new file mode 100644 index 0000000..1163851 --- /dev/null +++ b/src/tests/key_enc_none.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMiE486eROKePG0/ +639D4XTTDR9XSRWp1xqZzq7P+jjWRFbZ/MWVIVzkc4MRm83UOolbPj76LjM10cse +aVAhK7G9CHp2dur4alWvdCXPH5Q+LPOFS9gMx0Jz9EZeHHOHZKLyJdKSmot+zluw +JTLe081RRUwzNKct6JrVVG/7SmITAgMBAAECgYB8ssfI0nwcQjNp7XpSZrBqqmVa +vDljE4AFtujlpckCV52gNWgQp7Fbx2ZeeDDgS78rdGa9W3AnwKx7GKp9fmNgxT5g +pFvDDpWqv+m6chSGIQdVqscwUob3KjXipJrPbE+Be8Lmnv9GFyL6sBSnfpLmQgdy +HmwuEQRwlrLKbLMPIQJBAP/kHcl2lyi+tIj6fJnwi5vb4jd/e6jHqbUMrEd5p3bo +gKgivtUKc9XknWAsgHYyh9UJsqGbLg82LlrRB29rMl8CQQDImr1j71JDiwI5UOsW +SUnGFe5kThZudHfZewF2dD11q6jQTa8NWS/qYefMxauhOMu/iEfme58Tk28yjw80 +YHTNAkAU4qR/vfsmazJG/9LNqbFrXi3/g5svMmSqj0c8ajR94wolLvjOYJUFvywN +HnS5sPQfMjRvNkAzI6Py656kvGYXAkAf5FHluF94s3nYCOBG+8HJxyTON4fjaYrA +PYj+/v3iXjcJXsBMu/gdKBGFAYwGppPl0FG198NThmXwQMQnDIqlAkEAnY01pxRF +PJq9Tr31Ak4h0YCwDgpeJyLwfc+65Yy0ctFEp08V5oJGf72ntOCV/Ssf2FQY6lRc +dgPf4QK3qCdUNw== +-----END PRIVATE KEY----- -- 2.7.4