--- /dev/null
+.config
+build-stamp
--- /dev/null
+COMPILING and INSTALLING:
+
+If you got a official release tar archive do:
+ ./configure
+
+( otherwise if you got this from enlightenment cvs do: ./autogen.sh )
+
+Then to compile:
+ make
+
+To install (run this as root, or the user who handles installs):
+ make install
+
+NOTE: You MUST make install Eet for it to run properly.
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = src
+
+MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess \
+ config.h.in config.sub configure install-sh \
+ ltconfig ltmain.sh missing mkinstalldirs \
+ stamp-h.in
+
+EXTRA_DIST = README AUTHORS COPYING eet.spec
--- /dev/null
+#undef PACKAGE_SOURCE_DIR
+#undef PACKAGE_BIN_DIR
+#undef PACKAGE_LIB_DIR
--- /dev/null
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+PKG_NAME="the package."
+
+DIE=0
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`autoconf' installed to."
+ echo "Download the appropriate package for your distribution,"
+ echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+}
+
+(grep "^AM_PROG_LIBTOOL" $srcdir/configure.in >/dev/null) && {
+ (libtool --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`libtool' installed."
+ echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.2d.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+ }
+}
+
+grep "^AM_GNU_GETTEXT" $srcdir/configure.in >/dev/null && {
+ grep "sed.*POTFILES" $srcdir/configure.in >/dev/null || \
+ (gettext --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`gettext' installed."
+ echo "Get ftp://alpha.gnu.org/gnu/gettext-0.10.35.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+ }
+}
+
+(automake --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`automake' installed."
+ echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+ NO_AUTOMAKE=yes
+}
+
+
+# if no automake, don't bother testing for aclocal
+test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: Missing \`aclocal'. The version of \`automake'"
+ echo "installed doesn't appear recent enough."
+ echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+}
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+if test -z "$*"; then
+ echo "**Warning**: I am going to run \`configure' with no arguments."
+ echo "If you wish to pass any to it, please specify them on the"
+ echo \`$0\'" command line."
+ echo
+fi
+
+case $CC in
+xlc )
+ am_opt=--include-deps;;
+esac
+
+for coin in `find $srcdir -name configure.in -print`
+do
+ dr=`dirname $coin`
+ if test -f $dr/NO-AUTO-GEN; then
+ echo skipping $dr -- flagged as no auto-gen
+ else
+ echo processing $dr
+ macrodirs=`sed -n -e 's,AM_ACLOCAL_INCLUDE(\(.*\)),\1,gp' < $coin`
+ ( cd $dr
+ aclocalinclude="$ACLOCAL_FLAGS"
+ for k in $macrodirs; do
+ if test -d $k; then
+ aclocalinclude="$aclocalinclude -I $k"
+ ##else
+ ## echo "**Warning**: No such directory \`$k'. Ignored."
+ fi
+ done
+ if grep "^AM_GNU_GETTEXT" configure.in >/dev/null; then
+ if grep "sed.*POTFILES" configure.in >/dev/null; then
+ : do nothing -- we still have an old unmodified configure.in
+ else
+ echo "Creating $dr/aclocal.m4 ..."
+ test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
+ echo "Running gettextize... Ignore non-fatal messages."
+ echo "no" | gettextize --force --copy
+ echo "Making $dr/aclocal.m4 writable ..."
+ test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
+ fi
+ fi
+ if grep "^AM_GNOME_GETTEXT" configure.in >/dev/null; then
+ echo "Creating $dr/aclocal.m4 ..."
+ test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
+ echo "Running gettextize... Ignore non-fatal messages."
+ echo "no" | gettextize --force --copy
+ echo "Making $dr/aclocal.m4 writable ..."
+ test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
+ fi
+ if grep "^AM_PROG_LIBTOOL" configure.in >/dev/null; then
+ echo "Running libtoolize..."
+ libtoolize --force --copy
+ fi
+ echo "Running aclocal $aclocalinclude ..."
+ aclocal $aclocalinclude
+ if grep "^AM_CONFIG_HEADER" configure.in >/dev/null; then
+ echo "Running autoheader..."
+ autoheader
+ fi
+ echo "Running automake --gnu $am_opt ..."
+ automake --add-missing --gnu $am_opt
+ echo "Running autoconf ..."
+ autoconf
+ )
+ fi
+done
+
+#conf_flags="--enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c
+
+if test x$NOCONFIGURE = x; then
+ echo Running $srcdir/configure $conf_flags "$@" ...
+ $srcdir/configure $conf_flags "$@" \
+ && echo Now type \`make\' to compile $PKG_NAME
+else
+ echo Skipping configure process.
+fi
--- /dev/null
+dnl Process this file with autoconf to produce a configure script.
+
+# get rid of that stupid cache mechanism
+rm -f config.cache
+
+AC_INIT(configure.in)
+AM_INIT_AUTOMAKE(eet, 0.0.1)
+AM_CONFIG_HEADER(config.h)
+
+AC_ISC_POSIX
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_HEADER_STDC
+AC_C_CONST
+AM_ENABLE_SHARED
+AM_PROG_LIBTOOL
+
+if test "x${exec_prefix}" = "xNONE"; then
+ if test "x${prefix}" = "xNONE"; then
+ bindir="${ac_default_prefix}/bin";
+ else
+ bindir="${prefix}/bin";
+ fi
+else
+ if test "x${prefix}" = "xNONE"; then
+ bindir="${ac_default_prefix}/bin";
+ else
+ bindir="${prefix}/bin";
+ fi
+fi
+
+if test "x${exec_prefix}" = "xNONE"; then
+ if test "x${prefix}" = "xNONE"; then
+ libdir="${ac_default_prefix}/lib";
+ else
+ libdir="${prefix}/lib";
+ fi
+else
+ if test "x${prefix}" = "xNONE"; then
+ libdir="${ac_default_prefix}/lib";
+ else
+ libdir="${prefix}/lib";
+ fi
+fi
+
+dnl Set PACKAGE_BIN_DIR in config.h.
+if test "x${bindir}" = 'xNONE'; then
+ if test "x${prefix}" = "xNONE"; then
+ AC_DEFINE_UNQUOTED(PACKAGE_BIN_DIR, "${ac_default_prefix}/bin")
+ else
+ AC_DEFINE_UNQUOTED(PACKAGE_BIN_DIR, "${prefix}/bin")
+ fi
+else
+ AC_DEFINE_UNQUOTED(PACKAGE_BIN_DIR, "${bindir}")
+fi
+
+dnl Set PACKAGE_LIB_DIR in config.h.
+if test "x${libdir}" = 'xNONE'; then
+ if test "x${prefix}" = "xNONE"; then
+ AC_DEFINE_UNQUOTED(PACKAGE_LIB_DIR, "${ac_default_prefix}/lib")
+ else
+ AC_DEFINE_UNQUOTED(PACKAGE_LIB_DIR, "${prefix}/lib")
+ fi
+else
+ AC_DEFINE_UNQUOTED(PACKAGE_LIB_DIR, "${libdir}")
+fi
+
+dnl Set PACKAGE_SOURCE_DIR in config.h.
+packagesrcdir=`cd $srcdir && pwd`
+AC_DEFINE_UNQUOTED(PACKAGE_SOURCE_DIR, "${packagesrcdir}")
+
+AC_OUTPUT([
+Makefile src/Makefile src/lib/Makefile src/bin/Makefile
+])
+
--- /dev/null
+dnl Process this file with autoconf to produce a configure script.
+
+# get rid of that stupid cache mechanism
+rm -f config.cache
+
+AC_INIT(configure.in)
+AM_INIT_AUTOMAKE(eet, 0.0.1)
+AM_CONFIG_HEADER(config.h)
+
+AC_ISC_POSIX
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_HEADER_STDC
+AC_C_CONST
+AM_ENABLE_SHARED
+AM_PROG_LIBTOOL
+
+if test "x${exec_prefix}" = "xNONE"; then
+ if test "x${prefix}" = "xNONE"; then
+ bindir="${ac_default_prefix}/bin";
+ else
+ bindir="${prefix}/bin";
+ fi
+else
+ if test "x${prefix}" = "xNONE"; then
+ bindir="${ac_default_prefix}/bin";
+ else
+ bindir="${prefix}/bin";
+ fi
+fi
+
+if test "x${exec_prefix}" = "xNONE"; then
+ if test "x${prefix}" = "xNONE"; then
+ libdir="${ac_default_prefix}/lib";
+ else
+ libdir="${prefix}/lib";
+ fi
+else
+ if test "x${prefix}" = "xNONE"; then
+ libdir="${ac_default_prefix}/lib";
+ else
+ libdir="${prefix}/lib";
+ fi
+fi
+
+dnl Set PACKAGE_BIN_DIR in config.h.
+if test "x${bindir}" = 'xNONE'; then
+ if test "x${prefix}" = "xNONE"; then
+ AC_DEFINE_UNQUOTED(PACKAGE_BIN_DIR, "${ac_default_prefix}/bin")
+ else
+ AC_DEFINE_UNQUOTED(PACKAGE_BIN_DIR, "${prefix}/bin")
+ fi
+else
+ AC_DEFINE_UNQUOTED(PACKAGE_BIN_DIR, "${bindir}")
+fi
+
+dnl Set PACKAGE_LIB_DIR in config.h.
+if test "x${libdir}" = 'xNONE'; then
+ if test "x${prefix}" = "xNONE"; then
+ AC_DEFINE_UNQUOTED(PACKAGE_LIB_DIR, "${ac_default_prefix}/lib")
+ else
+ AC_DEFINE_UNQUOTED(PACKAGE_LIB_DIR, "${prefix}/lib")
+ fi
+else
+ AC_DEFINE_UNQUOTED(PACKAGE_LIB_DIR, "${libdir}")
+fi
+
+dnl Set PACKAGE_SOURCE_DIR in config.h.
+packagesrcdir=`cd $srcdir && pwd`
+AC_DEFINE_UNQUOTED(PACKAGE_SOURCE_DIR, "${packagesrcdir}")
+
+AC_OUTPUT([
+Makefile src/Makefile src/lib/Makefile src/bin/Makefile
+])
+
--- /dev/null
+files
+libeet0
+libeet0-dev
+libeet0.postinst.debhelper
+libeet0.postrm.debhelper
+libeet0.substvars
+tmp
--- /dev/null
+libeet (0.0.0-0cvs20021005) unstable; urgency=low
+
+ * a CVS release
+
+ -- Sytse Wielinga <s.b.wielinga@student.utwente.nl> Sat, 5 Oct 2002 12:12:06 +0200
+
--- /dev/null
+Source: libeet
+Section: libs
+Priority: optional
+Maintainer: Sytse Wielinga <s.b.wielinga@student.utwente.nl>
+Build-Depends: debhelper (>> 3.0.0), libz-dev, libjpeg-dev
+Standards-Version: 3.5.7.0
+
+Package: libeet0-dev
+Section: devel
+Architecture: any
+Depends: libeet0 (= ${Source-Version})
+Provides: libeet-dev
+Conflicts: libeet-dev
+Description: Enlightenment file chunk reading/writing library development files
+ This package contains headers and static libraries for development with
+ libeet.
+
+Package: libeet0
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: Enlightenment file chunk reading/writing library
+ 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.
+ .
+ It's small, fast, and does a job. It's heavily commented and fully documented.
--- /dev/null
+This package was debianized by Sytse Wielinga <s.b.wielinga@student.utwente.nl> on
+Thu, 3 Oct 2002 12:08:24 +0200.
+
+The source is downloaded from the e17/libs/eet module of the enlightenment CVS
+tree. For more information, see:
+
+ http://www.enlightenment.org/cvs.html
+
+Upstream Author(s): Enlightenment team <enlightenment-devel@lists.sourceforge.net>
+
+Copyright:
+
+Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS)
+
+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.
+
+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.
--- /dev/null
+.\" Hey, EMACS: -*- nroff -*-
+.TH EET 1 "oktober 3, 2002"
+.SH NAME
+eet-config \- script to get information about the installed version of Eet
+.SH SYNOPSIS
+.B eet-config [\-\-version] [\-\-libs] [\-\-cflags]
+.SH DESCRIPTION
+\fIeet-config\fP is a tool that is used by configure to determine the
+availability of eet and the compiler and linker flags that should be used to
+compile programs using it.
+.SH OPTIONS
+\fIeet-config\fP accepts the following options:
+.TP
+.B \-\-version
+Print the currently installed version of \fIeet\fP on the standard output.
+.TP
+.B \-\-libs
+Print the linker flags that are necessary to link a \fIeet\fP\-program.
+.TP
+.B \-\-cflags
+Print the compiler flags that are necessary to link a \fIeet\fP\-program.
+.SH SEE ALSO
+.BR eet (1).
+.SH AUTHOR
+This manual page was written by Sytse Wielinga
+<s.b.wielinga@student.utwente.nl> for the Debian GNU/Linux system (but may be
+used by others).
--- /dev/null
+.\" Hey, EMACS: -*- nroff -*-
+.TH EET 1 "oktober 3, 2002"
+.SH NAME
+eet \- program for editing eet files
+.SH SYNOPSIS
+.B eet
+-l in_file
+.br
+.B eet
+-d in_file
+.br
+.B eet
+-c out_file [-nz glob [-nz glob ...]] dir_file1 [dir_file2 ...]
+.SH DESCRIPTION
+This manual page documents briefly the
+.B eet
+command.
+This manual page was written for the Debian distribution
+because the original program does not have a manual page.
+.PP
+.B eet
+is a program for viewing, unpacking and adding files to eet files, which are
+containers for optionally compressed data, allowing for fast random-access
+reading. These files are mostly used by the enlightenment project. See
+.B www.enlightenment.org
+for more details about this project.
+.SH OPTIONS
+.TP
+.B \-l in_file
+List the contents of an eet file
+.TP
+.B \-d in_file
+Unpack an eet file
+.TP
+.B \-c out_file
+Create an eet file
+.TP
+.B \-nz match
+Store files matching match glob uncompressed
+.SH SEE ALSO
+.BR eet-config (1).
+.PP
+For more information, have a look at the sources of libeet. To get them, have
+a look at the website
+.B www.enlightenment.org
+or execute the following commands:
+.TP
+.B export CVSROOT=:pserver:anonymous@cvs.enlightenment.sourceforge.net:/cvsroot/enlightenment
+If this is command is broken among multiple lines because your terminal is not
+as wide as the command, please don't include the minus sign into the command.
+.TP
+.B cvs login
+Just hit enter if it asks about a password for anonymous.
+.TP
+.B cvs co -r SPLIT e17/libs/eet
+This command should create the directory e17/libs/eet, containing the latest
+sources of eet.
+.SH AUTHOR
+This manual page was written by Sytse Wielinga
+<s.b.wielinga@student.utwente.nl> for the Debian GNU/Linux system (but may be
+used by others).
--- /dev/null
+usr/bin/eet-config
+usr/include/*
+usr/lib/lib*.a
+usr/lib/lib*.so
--- /dev/null
+usr/bin/eet
+usr/lib/lib*.so.*
--- /dev/null
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# GNU copyright 1997 to 1999 by Joey Hess.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# This is the debhelper compatibility version to use.
+export DH_COMPAT=3
+
+
+ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
+ CFLAGS += -g
+endif
+ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
+ INSTALL_PROGRAM += -s
+endif
+
+version=`ls src/.libs/lib*.so.* | \
+ awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
+major=`ls src/.libs/lib*.so.* | \
+ awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
+
+build: build-stamp
+build-stamp:
+ dh_testdir
+
+ ./configure --prefix=/usr build
+
+ touch build-stamp
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp
+
+ -./configure clean
+
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ ./configure --prefix=$(CURDIR)/debian/tmp/usr install
+
+
+binary-indep: build install
+
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_movefiles
+
+ dh_installdocs -plibeet0 README AUTHORS
+ dh_installdocs -plibeet0-dev
+ dh_installman -plibeet0 debian/eet.1
+ dh_installman -plibeet0-dev debian/eet-config.1
+ dh_installchangelogs
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_makeshlibs
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
--- /dev/null
+#!/bin/sh
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+exec_prefix_set=no
+
+usage="\
+Usage: evas-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]"
+
+if test $# -eq 0; then
+ echo "${usage}" 1>&2
+ exit 1
+fi
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case $1 in
+ --prefix=*)
+ prefix=$optarg
+ if test $exec_prefix_set = no ; then
+ exec_prefix=$optarg
+ fi
+ ;;
+ --prefix)
+ echo $prefix
+ ;;
+ --exec-prefix=*)
+ exec_prefix=$optarg
+ exec_prefix_set=yes
+ ;;
+ --exec-prefix)
+ echo $exec_prefix
+ ;;
+ --version)
+ echo @VERSION@
+ ;;
+ --cflags)
+ if test @includedir@ != /usr/include ; then
+ includes=-I@includedir@
+ fi
+ echo $includes
+ ;;
+ --libs)
+ libdirs=-L@libdir@
+ echo $libdirs -leet -ljpeg -lz
+ ;;
+ *)
+ echo "${usage}" 1>&2
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+exit 0
--- /dev/null
+# Note that this is NOT a relocatable package
+%define ver 0.0.1
+%define rel 1
+%define prefix /usr/local
+
+Summary: eet
+Name: eet
+Version: %ver
+Release: %rel
+Copyright: BSD
+Group: Base/Group
+Source: ftp://ftp.enlightenment.org/pub/eet/eet-%{ver}.tar.gz
+BuildRoot: /var/tmp/eet-root
+Packager: The Rasterman <raster@rasterman.com>
+URL: http://www.enlightenment.org/
+Requires: libjpeg
+Requires: zlib
+
+Docdir: %{prefix}/doc
+
+%description
+Eet
+
+%prep
+%setup
+
+%build
+./configure --prefix=%prefix
+
+if [ "$SMP" != "" ]; then
+ (make "MAKE=make -k -j $SMP"; exit 0)
+ make
+else
+ make
+fi
+###########################################################################
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make prefix=$RPM_BUILD_ROOT%{prefix} install
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+
+%postun
+
+%files
+%defattr(-,root,root)
+%doc README COPYING ChangeLog
+%attr(755,root,root) %{prefix}/bin/*
+%attr(755,root,root) %{prefix}/lib/*
+%{prefix}/share/*
+
+%doc AUTHORS
+%doc COPYING
+%doc README
+
+%changelog
+* Sat Jun 23 2001 The Rasterman <raster@rasterman.com>
+- Created spec file
+
--- /dev/null
+eet
+eet-config
+libeet.so.0.0.0
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = lib bin
--- /dev/null
+eet
+eet-config
+libeet.so.0.0.0
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+INCLUDES = \
+ -I../lib
+
+bin_PROGRAMS = eet
+
+eet_SOURCES = \
+eet_main.c
+
+eet_LDADD = $(top_builddir)/src/lib/libeet.la
+eet_DEPENDANCIES = $(top_builddir)/src/lib/libeet.la
--- /dev/null
+#include "Eet.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <limits.h>
+#include <fnmatch.h>
+
+/* just some sample code on how to use encoder/decoders */
+#if 0
+#include <Evas.h>
+
+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;
+
+void
+encdectest(void)
+{
+ 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_hash_foreach,
+ evas_hash_add);
+ 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_hash_foreach,
+ evas_hash_add);
+ 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_hash_foreach,
+ evas_hash_add);
+ 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);
+ f = fopen("out", "w");
+ if (f)
+ {
+ fwrite(data, size, 1, f);
+ fclose(f);
+ }
+ 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);
+
+ exit(0);
+}
+#endif
+
+int eet_mkdir(char *dir);
+void eet_mkdirs(char *s);
+
+void depak_file(Eet_File *ef, char *file);
+void depack(char *pak_file);
+
+void list(char *pak_file);
+
+void pak_file(Eet_File *ef, char *file, char **noz, int noz_num);
+void pak_dir(Eet_File *ef, char *dir, char **noz, int noz_num);
+void pack(char *pak_file, char **files, int count, char **noz, int noz_num);
+
+static mode_t default_mode =
+S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+
+int
+eet_mkdir(char *dir)
+{
+ if (mkdir(dir, default_mode) < 0) return 0;
+ return 1;
+}
+
+void
+eet_mkdirs(char *s)
+{
+ char ss[PATH_MAX];
+ int i, ii;
+
+ i = 0;
+ ii = 0;
+ while (s[i])
+ {
+ ss[ii++] = s[i];
+ ss[ii] = 0;
+ if (s[i] == '/') eet_mkdir(ss);
+ i++;
+ }
+}
+
+void
+depak_file(Eet_File *ef, char *file)
+{
+ void *data;
+ int size;
+ char *last;
+
+ data = eet_read(ef, file, &size);
+ if (data)
+ {
+ FILE *f;
+ char buf[PATH_MAX];
+
+ strcpy(buf, file);
+ last = strrchr(buf, '/');
+ if (last)
+ {
+ last[1] = 0;
+ eet_mkdirs(buf);
+ }
+
+ f = fopen(file, "w");
+ if (f)
+ {
+ fwrite(data, 1, size, f);
+ fclose(f);
+ printf("exported: %s\n", file);
+ }
+ else
+ printf("error exporting: %s\n", file);
+ free(data);
+ }
+ else
+ {
+ printf("error reading: %s\n", file);
+ }
+}
+
+void
+depack(char *pak_file)
+{
+ int i, num;
+ char **list;
+ Eet_File *ef;
+
+ ef = eet_open(pak_file, EET_FILE_MODE_READ);
+ if (!ef)
+ {
+ printf("cannot open for reading: %s\n", pak_file);
+ return;
+ }
+ list = eet_list(ef, "*", &num);
+ if (list)
+ {
+ for (i = 0; i < num; i++)
+ depak_file(ef, list[i]);
+ free(list);
+ }
+ eet_close(ef);
+}
+
+void
+list(char *pak_file)
+{
+ int i, num;
+ char **list;
+ Eet_File *ef;
+
+ ef = eet_open(pak_file, EET_FILE_MODE_READ);
+ if (!ef)
+ {
+ printf("cannot open for reading: %s\n", pak_file);
+ return;
+ }
+ list = eet_list(ef, "*", &num);
+ if (list)
+ {
+ for (i = 0; i < num; i++)
+ printf("%s\n",list[i]);
+ free(list);
+ }
+ eet_close(ef);
+}
+
+void
+pak_file(Eet_File *ef, char *file, char **noz, int noz_num)
+{
+ struct stat st;
+
+ if (stat(file, &st) >= 0)
+ {
+ void *buf;
+
+ buf = malloc(st.st_size);
+ if (buf)
+ {
+ FILE *f;
+
+ f = fopen(file, "r");
+ if (f)
+ {
+ int compress = 1;
+ int i;
+
+ for (i = 0; i < noz_num; i++)
+ {
+ if (!fnmatch(noz[i], file, 0))
+ {
+ compress = 0;
+ break;
+ }
+ }
+ fread(buf, 1, st.st_size, f);
+ if (!eet_write(ef, file, buf, st.st_size, compress))
+ printf("error importing: %s\n", file);
+ else
+ {
+ if (compress)
+ printf("compress: %s\n", file);
+ else
+ printf("imported: %s\n", file);
+ }
+ fclose(f);
+ }
+ free(buf);
+ }
+ }
+}
+
+void
+pak_dir(Eet_File *ef, char *dir, char **noz, int noz_num)
+{
+ DIR *dirp;
+ struct dirent *dp;
+
+ dirp = opendir(dir);
+ if (!dirp)
+ pak_file(ef, dir, noz, noz_num);
+ else
+ {
+ while ((dp = readdir(dirp)))
+ {
+ char buf[PATH_MAX];
+
+ if ((!strcmp(".", dp->d_name)) || (!strcmp("..", dp->d_name)))
+ {
+ }
+ else
+ {
+ snprintf(buf, sizeof(buf), "%s/%s", dir, dp->d_name);
+ pak_dir(ef, buf, noz, noz_num);
+ }
+ }
+ }
+}
+
+void
+pack(char *pak_file, char **files, int count, char **noz, int noz_num)
+{
+ Eet_File *ef;
+ int i;
+
+ ef = eet_open(pak_file, EET_FILE_MODE_WRITE);
+ if (!ef)
+ {
+ printf("cannot open for writing: %s\n", pak_file);
+ return;
+ }
+ for (i = 0; i < count; i++) pak_dir(ef, files[i], noz, noz_num);
+ printf("done.\n");
+ eet_close(ef);
+}
+
+int
+main(int argc, char **argv)
+{
+ if (argc == 3)
+ {
+ if (!strcmp(argv[1], "-d"))
+ {
+ depack(argv[2]);
+ return 0;
+ }
+ else if (!strcmp(argv[1], "-l"))
+ {
+ list(argv[2]);
+ return 0;
+ }
+ }
+ else if (argc > 3)
+ {
+ char **noz = NULL;
+ int noz_num = 0;
+
+ if (!strcmp(argv[1], "-c"))
+ {
+ int i;
+
+ for (i = 3; i < argc; i++)
+ {
+ if (!strcmp(argv[i], "-nz"))
+ {
+ if (i < (argc - 1))
+ {
+ i++;
+ noz_num++;
+ noz = realloc(noz, noz_num * sizeof(char *));
+ noz[noz_num - 1] = argv[i];
+ }
+ }
+ else
+ break;
+ }
+ pack(argv[2], &(argv[i]), argc - i, noz, noz_num);
+ return 0;
+ }
+ }
+ printf("usage:\n"
+ " %s -l in_file\n"
+ " %s -d in_file\n"
+ " %s -c out_file [-nz glob [-nz glob ...]] dir_file1 [dir_file2 ...]\n"
+ "\n"
+ "where:\n"
+ " -l in_file list contents of eet file\n"
+ " -d in_file unpack eet file\n"
+ " -c out_file pack up eet file\n"
+ " -nz match don't compress files matching match glob\n"
+ "\n"
+ "example:\n"
+ " %s -c out.eet -nz \"*.jpg\" things/\n"
+ " %s -l out.eet\n"
+ " %s -d out.eet\n",
+ argv[0], argv[0], argv[0],
+ argv[0], argv[0], argv[0]);
+ return -1;
+}
--- /dev/null
+eet
+eet-config
+libeet.so.0.0.0
--- /dev/null
+#ifndef _EET_H
+#define _EET_H
+
+/***************************************************************************/
+
+/*
+ * EET - E file chunk reading/writing library
+ *
+ * What is it?
+ * It 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 impliment this once here.
+ *
+ */
+
+/***************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************/
+
+#define EET_T_UNKNOW 0
+#define EET_T_CHAR 1
+#define EET_T_SHORT 2
+#define EET_T_INT 3
+#define EET_T_LONG_LONG 4
+#define EET_T_FLOAT 5
+#define EET_T_DOUBLE 6
+#define EET_T_UCHAR 7
+#define EET_T_USHORT 8
+#define EET_T_UINT 9
+#define EET_T_ULONG_LONG 10
+#define EET_T_STRING 11
+#define EET_T_LAST 12
+
+#define EET_G_UNKNOWN 100
+#define EET_G_ARRAY 101
+#define EET_G_VAR_ARRAY 102
+#define EET_G_LIST 103
+#define EET_G_HASH 104
+#define EET_G_LAST 105
+
+/***************************************************************************/
+
+ enum _Eet_File_Mode
+ {
+ EET_FILE_MODE_READ,
+ EET_FILE_MODE_WRITE
+ };
+
+ typedef enum _Eet_File_Mode Eet_File_Mode;
+
+ typedef struct _Eet_File Eet_File;
+ typedef struct _Eet_Data_Descriptor Eet_Data_Descriptor;
+
+
+/***************************************************************************/
+
+ /* eet_open - Open an eet file on disk, and returns a handle to it.
+ * @file: The file path to the eet file. eg: "/tmp/file.eet".
+ * @mode: The mode for opening. Either EET_FILE_MODE_READ or EET_FILE_MODE_WRITE, but not both.
+ *
+ * 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.
+ */
+ Eet_File *eet_open (char *file, Eet_File_Mode mode);
+ /* eet_close - Close an eet file handle and flush and writes pending.
+ * @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.
+ */
+ void eet_close (Eet_File *ef);
+ /* eet_read - Read a specified entry from an eet file and return data
+ * @ef: A valid eet file handle opened for reading.
+ * @name: Name of the entry. eg: "/base/file_i_want".
+ * @size_ret: Number of bytes read from entry and returned.
+ *
+ * This function finds an entry in the eet file that is stored under the
+ * name specified, and returns that data, decompressed, if successfule.
+ * NULL is retuurned 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.
+ */
+ void *eet_read (Eet_File *ef, char *name, int *size_ret);
+ /* eet_write - Write a specified entry to an eet file handle
+ * @ef: A valid eet file handle opened for writing.
+ * @name: Name of the entry. eg: "/base/file_i_want".
+ * @data: Pointer to the data to be stored.
+ * @size: Length in bytes in the data to be stored.
+ * @compress: Compression flags (1 == compress, 0 = don't compress).
+ *
+ * This function will write the specified chunk of data to the eet file
+ * and return 1 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).
+ */
+ int eet_write (Eet_File *ef, char *name, void *data, int size, int compress);
+ /* eet_list - List all entries in eet file matching shell glob.
+ * @ef: A valid eet file handle.
+ * @glob: A shell glob to match against.
+ * @count_ret: number of entries foudn to match.
+ *
+ * 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 "*".
+ */
+ char **eet_list (Eet_File *ef, char *glob, int *count_ret);
+
+/***************************************************************************/
+
+ /* eet_data_image_read - Read image data from the named key in the eet file.
+ * @ef: A valid eet file handle opened for reading.
+ * @name: Name of the entry. eg: "/base/file_i_want".
+ * @w: A pointer to the int to hold the width in pixels.
+ * @h: A pointer to the int to hold the height in pixels.
+ * @alpha: A pointer to the int to hold the alpha flag.
+ * @compress: A pointer to the int to hold the compression amount.
+ * @quality: A pointer to the int to hold the quality amount.
+ * @lossy: A pointer to the int to hold the lossiness flag.
+ *
+ * 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 piel 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 denoties that it is significant.
+ * Compress is fiulled with the compression value/amount the image was
+ * stored with. The quality value si fileld 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.
+ */
+ void *eet_data_image_read(Eet_File *ef, char *name, int *w, int *h, int *alpha, int *compress, int *quality, int *lossy);
+ /* eet_data_image_write - Write image data to the named key in an eet file.
+ * @ef: A valid eet file handle opened for writing.
+ * @name: Name of the entry. eg: "/base/file_i_want".
+ * @data: A pointer to the image pixel data.
+ * @w: The width of the image in pixels.
+ * @h: The height of the image in pixels.
+ * @alpha: The alpha channel flag.
+ * @compress: The compression amount.
+ * @quality: The quality encoding amount.
+ * @lossy: The lossiness flag.
+ *
+ * This function dates 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 wierd 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 shoudl 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 rtuens the numebr fo bytes that were required
+ * to encode the image data, or on failure it returns 0.
+ */
+ int eet_data_image_write(Eet_File *ef, char *name, void *data, int w, int h, int alpha, int compress, int quality, int lossy);
+
+ /* To Be Documented
+ *
+ */
+ void *eet_data_image_encode(void *data, int *size_ret, int w, int h, int alpha, int compress, int quality, int lossy);
+ void *eet_data_image_decode(void *data, int size, int *w, int *h, int *alpha, int *compress, int *quality, int *lossy);
+/***************************************************************************/
+
+ /* To Be Documented
+ *
+ */
+ Eet_Data_Descriptor *eet_data_descriptor_new(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_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 eet_data_descriptor_free(Eet_Data_Descriptor *edd);
+
+ void eet_data_descriptor_element_add(Eet_Data_Descriptor *edd, char *name, int type, int group_type, int offset, int count, char *counter_name, Eet_Data_Descriptor *subtype);
+
+ void *eet_data_read(Eet_File *ef, Eet_Data_Descriptor *edd, char *name);
+ int eet_data_write(Eet_File *ef, Eet_Data_Descriptor *edd, char *name, void *data, int compress);
+
+ void *eet_data_descriptor_decode(Eet_Data_Descriptor *edd, void *data_in, int size_in);
+ void *eet_data_descriptor_encode(Eet_Data_Descriptor *edd, void *data_in, int *size_ret);
+
+#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, NULL, NULL); \
+ }
+#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, NULL, subtype); \
+ }
+#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, NULL, subtype); \
+ }
+
+/***************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS = 1.4 foreign
+
+# A list of all the files in the current directory which can be regenerated
+MAINTAINERCLEANFILES = Makefile.in
+
+LDFLAGS = -L/usr/local/lib
+INCLUDES = -I/usr/local/include \
+ -I$(includedir)
+
+lib_LTLIBRARIES = libeet.la
+include_HEADERS = Eet.h
+libeet_la_SOURCES = \
+eet_lib.c \
+eet_data.c
+
+libeet_la_LIBADD = $(LDFLAGS) -lz -ljpeg
+libeet_la_DEPENDENCIES = $(top_builddir)/config.h
+libeet_la_LDFLAGS = -version-info 0:1:0
--- /dev/null
+#include "Eet.h"
+#define _GNU_SOURCE /* need this for fmemopen & open_memstream */
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <zlib.h>
+#include <string.h>
+#include <fnmatch.h>
+#include <jpeglib.h>
+#include <setjmp.h>
+#include <zlib.h>
+#include <locale.h>
+
+
+/*
+ * rotuines for doing data -> struct and struct -> data conversion
+ *
+ * types:
+ *
+ * basic types:
+ * a sequence of...
+ *
+ * char
+ * short
+ * int
+ * long long
+ * float
+ * double
+ * unsigned char
+ * unsigned short
+ * unsigned int
+ * unsgined long long
+ * string
+ *
+ * groupings:
+ * multiple entries ordered as...
+ *
+ * fixed size array [ of basic types ]
+ * variable size array [ of basic types ]
+ * linked list [ of basic types ]
+ * hash table [ of basic types ]
+ *
+ * need to provide builder/accessor funcs for:
+ *
+ * list_next
+ * list_append
+ *
+ * hash_foreach
+ * hash_add
+ *
+ */
+
+/*---*/
+
+typedef struct _Eet_Data_Element Eet_Data_Element;
+typedef struct _Eet_Data_Basic_Type_Decoder Eet_Data_Basic_Type_Decoder;
+typedef struct _Eet_Data_Chunk Eet_Data_Chunk;
+typedef struct _Eet_Data_Stream Eet_Data_Stream;
+typedef struct _JPEG_error_mgr *emptr;
+
+/*---*/
+
+struct _Eet_Data_Basic_Type_Decoder
+{
+ int size;
+ int (*get) (void *src, void *src_end, void *dest);
+ void *(*put) (void *src, int *size_ret);
+};
+
+struct _Eet_Data_Chunk
+{
+ char *name;
+ int size;
+ void *data;
+};
+
+struct _Eet_Data_Stream
+{
+ void *data;
+ int size;
+ int pos;
+};
+
+struct _Eet_Data_Descriptor
+{
+ char *name;
+ int size;
+ struct {
+ void *(*list_next) (void *l);
+ void *(*list_append) (void *l, void *d);
+ void *(*list_data) (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);
+ } func;
+ struct {
+ int num;
+ Eet_Data_Element *set;
+ } elements;
+};
+
+struct _Eet_Data_Element
+{
+ char *name;
+ int type;
+ int group_type;
+ int offset;
+ int count;
+ char *counter_name;
+ Eet_Data_Descriptor *subtype;
+};
+
+struct _JPEG_error_mgr
+{
+ struct jpeg_error_mgr pub;
+ jmp_buf setjmp_buffer;
+};
+
+/*---*/
+
+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 *eet_data_image_jpeg_rgb_decode(void *data, int size, int *w, int *h);
+static void *eet_data_image_jpeg_alpha_decode(void *data, int size, unsigned int *d, int *w, int *h);
+static void *eet_data_image_lossless_convert(int *size, void *data, int w, int h, int alpha);
+static void *eet_data_image_lossless_compressed_convert(int *size, void *data, int w, int h, int alpha, int compression);
+static void *eet_data_image_jpeg_convert(int *size, void *data, int w, int h, int alpha, int quality);
+static void *eet_data_image_jpeg_alpha_convert(int *size, void *data, int w, int h, int alpha, int quality);
+
+static int eet_data_get_char(void *src, void *src_end, void *dest);
+static void *eet_data_put_char(void *src, int *size_ret);
+static int eet_data_get_short(void *src, void *src_end, void *dest);
+static void *eet_data_put_short(void *src, int *size_ret);
+static int eet_data_get_int(void *src, void *src_end, void *dest);
+static void *eet_data_put_int(void *src, int *size_ret);
+static int eet_data_get_long_long(void *src, void *src_end, void *dest);
+static void *eet_data_put_long_long(void *src, int *size_ret);
+static int eet_data_get_float(void *src, void *src_end, void *dest);
+static void *eet_data_put_float(void *src, int *size_ret);
+static int eet_data_get_double(void *src, void *src_end, void *dest);
+static void *eet_data_put_double(void *src, int *size_ret);
+static int eet_data_get_string(void *src, void *src_end, void *dest);
+static void *eet_data_put_string(void *src, int *size_ret);
+
+static int eet_data_get_type(int type, void *src, void *src_end, void *dest);
+static void *eet_data_put_type(int type, void *src, int *size_ret);
+
+static Eet_Data_Chunk *eet_data_chunk_get(void *src, int size);
+static Eet_Data_Chunk *eet_data_chunk_new(void *data, int size, char *name);
+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, void *data, int size);
+static void eet_data_stream_free(Eet_Data_Stream *ds);
+
+static void eet_data_chunk_put(Eet_Data_Chunk *chnk, Eet_Data_Stream *ds);
+
+/*---*/
+
+const Eet_Data_Basic_Type_Decoder eet_coder[] =
+{
+ {sizeof(char), eet_data_get_char, eet_data_put_char },
+ {sizeof(short), eet_data_get_short, eet_data_put_short },
+ {sizeof(int), eet_data_get_int, eet_data_put_int },
+ {sizeof(long long), eet_data_get_long_long, eet_data_put_long_long},
+ {sizeof(float), eet_data_get_float, eet_data_put_float },
+ {sizeof(double), eet_data_get_double, eet_data_put_double },
+ {sizeof(char), eet_data_get_char, eet_data_put_char },
+ {sizeof(short), eet_data_get_short, eet_data_put_short },
+ {sizeof(int), eet_data_get_int, eet_data_put_int },
+ {sizeof(long long), eet_data_get_long_long, eet_data_put_long_long},
+ {sizeof(char *), eet_data_get_string, eet_data_put_string }
+};
+
+static int words_bigendian = -1;
+
+/*---*/
+
+#define SWAP64(x) (x) = \
+ ((((x) & 0x00000000000000ff ) << 56) |\
+ (((x) & 0x000000000000ff00 ) << 40) |\
+ (((x) & 0x0000000000ff0000 ) << 24) |\
+ (((x) & 0x00000000ff000000 ) << 8) |\
+ (((x) & 0x000000ff00000000 ) >> 8) |\
+ (((x) & 0x0000ff0000000000 ) >> 24) |\
+ (((x) & 0x00ff000000000000 ) >> 40) |\
+ (((x) & 0xff00000000000000 ) >> 56))
+#define SWAP32(x) (x) = \
+ ((((x) & 0x000000ff ) << 24) |\
+ (((x) & 0x0000ff00 ) << 8) |\
+ (((x) & 0x00ff0000 ) >> 8) |\
+ (((x) & 0xff000000 ) >> 24))
+#define SWAP16(x) (x) = \
+ ((((x) & 0x00ff ) << 8) |\
+ (((x) & 0xff00 ) >> 8))
+
+#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);}
+
+/*---*/
+
+static void
+_JPEGFatalErrorHandler(j_common_ptr cinfo)
+{
+ emptr errmgr;
+
+ errmgr = (emptr) cinfo->err;
+ /* cinfo->err->output_message(cinfo);*/
+ longjmp(errmgr->setjmp_buffer, 1);
+ return;
+}
+
+static void
+_JPEGErrorHandler(j_common_ptr cinfo)
+{
+ emptr errmgr;
+
+ 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)
+{
+ emptr errmgr;
+
+ errmgr = (emptr) cinfo->err;
+ /* cinfo->err->output_message(cinfo);*/
+ /* longjmp(errmgr->setjmp_buffer, 1);*/
+ return;
+ msg_level = 0;
+}
+
+static void *
+eet_data_image_jpeg_rgb_decode(void *data, int size, int *w, int *h)
+{
+ unsigned int *d;
+ struct jpeg_decompress_struct cinfo;
+ struct _JPEG_error_mgr jerr;
+ unsigned char *ptr, *line[16], *tdata;
+ unsigned int *ptr2;
+ int x, y, l, i, scans, count, prevy;
+ FILE *f;
+
+ f = fmemopen(data, (size_t)size, "r");
+ if (!f) return NULL;
+ 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_decompress(&cinfo);
+ fclose(f);
+ return NULL;
+ }
+ jpeg_create_decompress(&cinfo);
+ jpeg_stdio_src(&cinfo, f);
+ jpeg_read_header(&cinfo, TRUE);
+ cinfo.do_fancy_upsampling = FALSE;
+ cinfo.do_block_smoothing = FALSE;
+ jpeg_start_decompress(&cinfo);
+
+ /* head decoding */
+ *w = cinfo.output_width;
+ *h = cinfo.output_height;
+ /* end head decoding */
+ /* data decoding */
+ if (cinfo.rec_outbuf_height > 16)
+ {
+ jpeg_destroy_decompress(&cinfo);
+ fclose(f);
+ return NULL;
+ }
+ tdata = malloc((*w) * 16 * 3);
+ if (!tdata)
+ {
+ jpeg_destroy_decompress(&cinfo);
+ fclose(f);
+ return NULL;
+ }
+ d = malloc((*w) * (*h) * 4);
+ if (!d)
+ {
+ free(tdata);
+ jpeg_destroy_decompress(&cinfo);
+ fclose(f);
+ return NULL;
+ }
+ ptr2 = d;
+ count = 0;
+ prevy = 0;
+ if (cinfo.output_components == 3)
+ {
+ for (i = 0; i < cinfo.rec_outbuf_height; i++)
+ line[i] = tdata + (i * (*w) * 3);
+ 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;
+ for (y = 0; y < scans; y++)
+ {
+ for (x = 0; x < (*w); x++)
+ {
+ *ptr2 =
+ (0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]);
+ ptr += 3;
+ ptr2++;
+ }
+ }
+ }
+ }
+ else 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;
+ for (y = 0; y < scans; y++)
+ {
+ for (x = 0; x < (*w); x++)
+ {
+ *ptr2 =
+ (0xff000000) | ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]);
+ ptr++;
+ ptr2++;
+ }
+ }
+ }
+ }
+ free(tdata);
+ fclose(f);
+ /* end data decoding */
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+ return d;
+}
+
+static void *
+eet_data_image_jpeg_alpha_decode(void *data, int size, unsigned int *d, int *w, int *h)
+{
+ struct jpeg_decompress_struct cinfo;
+ struct _JPEG_error_mgr jerr;
+ unsigned char *ptr, *line[16], *tdata;
+ unsigned int *ptr2;
+ int x, y, l, i, scans, count, prevy;
+ FILE *f;
+
+ f = fmemopen(data, (size_t)size, "r");
+ if (!f) return NULL;
+ 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_decompress(&cinfo);
+ fclose(f);
+ return NULL;
+ }
+ jpeg_create_decompress(&cinfo);
+ jpeg_stdio_src(&cinfo, f);
+ jpeg_read_header(&cinfo, TRUE);
+ cinfo.do_fancy_upsampling = FALSE;
+ cinfo.do_block_smoothing = FALSE;
+ jpeg_start_decompress(&cinfo);
+
+ /* head decoding */
+ if ((*w) != cinfo.output_width)
+ {
+ jpeg_destroy_decompress(&cinfo);
+ fclose(f);
+ return NULL;
+ }
+ if ((*h) != cinfo.output_height)
+ {
+ jpeg_destroy_decompress(&cinfo);
+ fclose(f);
+ return NULL;
+ }
+ *w = cinfo.output_width;
+ *h = cinfo.output_height;
+ /* end head decoding */
+ /* data decoding */
+ if (cinfo.rec_outbuf_height > 16)
+ {
+ jpeg_destroy_decompress(&cinfo);
+ fclose(f);
+ return NULL;
+ }
+ tdata = malloc((*w) * 16 * 3);
+ if (!tdata)
+ {
+ jpeg_destroy_decompress(&cinfo);
+ fclose(f);
+ return NULL;
+ }
+ ptr2 = d;
+ count = 0;
+ prevy = 0;
+ if (cinfo.output_components == 3)
+ {
+ for (i = 0; i < cinfo.rec_outbuf_height; i++)
+ line[i] = tdata + (i * (*w) * 3);
+ 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;
+ for (y = 0; y < scans; y++)
+ {
+ for (x = 0; x < (*w); x++)
+ {
+ *ptr2 =
+ ((*ptr2) & 0x00ffffff) |
+ (((ptr[0] + ptr[1] + ptr[2]) / 3) << 24);
+ ptr += 3;
+ ptr2++;
+ }
+ }
+ }
+ }
+ else 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;
+ for (y = 0; y < scans; y++)
+ {
+ for (x = 0; x < (*w); x++)
+ {
+ *ptr2 =
+ ((*ptr2) & 0x00ffffff) |
+ ((ptr[0]) << 24);
+ ptr++;
+ ptr2++;
+ }
+ }
+ }
+ }
+ free(tdata);
+ fclose(f);
+ /* end data decoding */
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+ return d;
+}
+
+static void *
+eet_data_image_lossless_convert(int *size, void *data, int w, int h, int alpha)
+{
+ if (words_bigendian == -1)
+ {
+ unsigned long int v;
+
+ v = htonl(0x12345678);
+ if (v == 0x12345678) words_bigendian = 1;
+ else words_bigendian = 0;
+ }
+ {
+ unsigned char *d;
+ int *header;
+
+ d = malloc((w * h * 4) + (8 * 4));
+ if (!d) return NULL;
+ header = (int *)d;
+ header[0] = 0xac1dfeed;
+ header[1] = w;
+ header[2] = h;
+ header[3] = alpha;
+ header[4] = 0;
+ memcpy(d + 32, data, w * h * 4);
+
+ if (words_bigendian)
+ {
+ 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, void *data, int w, int h, int alpha, int compression)
+{
+ if (words_bigendian == -1)
+ {
+ unsigned long int v;
+
+ v = htonl(0x12345678);
+ if (v == 0x12345678) words_bigendian = 1;
+ else 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;
+ 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)
+ {
+ 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);
+ *size = ((w * h * 4) + (8 * 4));
+ return d;
+ }
+ memcpy(d + 32, comp, buflen);
+ *size = (8 * 4) + buflen;
+ free(comp);
+ return d;
+ }
+}
+
+static void *
+eet_data_image_jpeg_convert(int *size, void *data, int w, int h, int alpha, int quality)
+{
+ int *ptr;
+ char *d = NULL;
+ size_t sz = 0;
+ struct _JPEG_error_mgr jerr;
+ JSAMPROW *jbuf;
+ struct jpeg_compress_struct cinfo;
+ FILE *f;
+ unsigned char *buf;
+
+ f = open_memstream(&d, &sz);
+ if (!f) return NULL;
+
+ buf = malloc(3 * w);
+ if (!buf)
+ {
+ fclose(f);
+ if (d) free(d);
+ return NULL;
+ }
+
+ 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);
+ if (buf) free(buf);
+ fclose(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);
+ jpeg_start_compress(&cinfo, TRUE);
+
+ ptr = data;
+ while (cinfo.next_scanline < cinfo.image_height)
+ {
+ 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);
+
+ *size = sz;
+ if (buf) free(buf);
+ fclose(f);
+ return d;
+}
+
+static void *
+eet_data_image_jpeg_alpha_convert(int *size, void *data, int w, int h, int alpha, int quality)
+{
+ unsigned char *d1, *d2;
+ unsigned char *d;
+ int *header;
+ int sz1, sz2;
+
+ if (words_bigendian == -1)
+ {
+ unsigned long int v;
+
+ v = htonl(0x12345678);
+ if (v == 0x12345678) words_bigendian = 1;
+ else words_bigendian = 0;
+ }
+
+ {
+ int *ptr;
+ char *d = NULL;
+ size_t sz = 0;
+ struct _JPEG_error_mgr jerr;
+ JSAMPROW *jbuf;
+ struct jpeg_compress_struct cinfo;
+ FILE *f;
+ unsigned char *buf;
+
+ f = open_memstream(&d, &sz);
+ if (!f) return NULL;
+
+ buf = malloc(3 * w);
+ if (!buf)
+ {
+ fclose(f);
+ if (d) free(d);
+ return NULL;
+ }
+
+ 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);
+ if (buf) free(buf);
+ fclose(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);
+ jpeg_start_compress(&cinfo, TRUE);
+
+ ptr = data;
+ while (cinfo.next_scanline < cinfo.image_height)
+ {
+ 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);
+
+ if (buf) free(buf);
+ fclose(f);
+ d1 = d;
+ sz1 = sz;
+ }
+ {
+ int *ptr;
+ char *d = NULL;
+ size_t sz = 0;
+ struct _JPEG_error_mgr jerr;
+ JSAMPROW *jbuf;
+ struct jpeg_compress_struct cinfo;
+ FILE *f;
+ unsigned char *buf;
+
+ f = open_memstream(&d, &sz);
+ if (!f)
+ {
+ free(d1);
+ return NULL;
+ }
+
+ buf = malloc(3 * w);
+ if (!buf)
+ {
+ fclose(f);
+ if (d) free(d);
+ free(d1);
+ return NULL;
+ }
+
+ 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);
+ if (buf) free(buf);
+ fclose(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);
+ jpeg_start_compress(&cinfo, TRUE);
+
+ ptr = data;
+ while (cinfo.next_scanline < cinfo.image_height)
+ {
+ 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);
+
+ if (buf) free(buf);
+ fclose(f);
+ d2 = d;
+ sz2 = sz;
+ }
+ d = malloc(12 + sz1 + sz2);
+ if (!d)
+ {
+ free(d1);
+ free(d2);
+ return NULL;
+ }
+ header = (int *)d;
+ header[0] = 0xbeeff00d;
+ header[1] = sz1;
+ header[2] = sz2;
+ if (words_bigendian)
+ {
+ int i;
+
+ for (i = 0; i < ((w * h) + 3); i++) SWAP32(header[i]);
+ }
+ memcpy(d + 12, d1, sz1);
+ memcpy(d + 12 + sz1, d2, sz2);
+
+ free(d1);
+ free(d2);
+ *size = 12 + sz1 + sz2;
+ return d;
+}
+
+
+/* CHAR TYPE */
+static int
+eet_data_get_char(void *src, void *src_end, void *dst)
+{
+ char *s, *d;
+
+ if ((src + sizeof(char)) > src_end) return -1;
+ s = (char *)src;
+ d = (char *)dst;
+ *s = *d;
+ CONV8(*s);
+ return sizeof(char);
+}
+
+static void *
+eet_data_put_char(void *src, int *size_ret)
+{
+ char *s, *d;
+
+ d = (char *)malloc(sizeof(char));
+ if (!d) return NULL;
+ s = (char *)src;
+ *d = *s;
+ CONV8(*d);
+ *size_ret = sizeof(char);
+ return d;
+}
+
+/* SHORT TYPE */
+static int
+eet_data_get_short(void *src, void *src_end, void *dst)
+{
+ short *s, *d;
+ short tmp;
+
+ if ((src + sizeof(short)) > src_end) return -1;
+ s = (short *)src;
+ d = (short *)dst;
+ /* alignment fixup */
+ if ((int)s & (sizeof(short) - 1))
+ {
+ memcpy(&tmp, s, sizeof(short));
+ s = &tmp;
+ }
+ *d = *s;
+ CONV16(*d);
+ return sizeof(short);
+}
+
+static void *
+eet_data_put_short(void *src, int *size_ret)
+{
+ short *s, *d;
+
+ d = (short *)malloc(sizeof(short));
+ if (!d) return NULL;
+ s = (short *)src;
+ *d = *s;
+ CONV16(*d);
+ *size_ret = sizeof(short);
+ return d;
+}
+
+/* INT TYPE */
+static int
+eet_data_get_int(void *src, void *src_end, void *dst)
+{
+ int *s, *d;
+ int tmp;
+
+ if ((src + sizeof(int)) > src_end) return -1;
+ s = (int *)src;
+ d = (int *)dst;
+ /* alignment fixup */
+ if ((int)s & (sizeof(int) - 1))
+ {
+ memcpy(&tmp, s, sizeof(int));
+ s = &tmp;
+ }
+ *d = *s;
+ CONV32(*d);
+ return sizeof(int);
+}
+
+static void *
+eet_data_put_int(void *src, int *size_ret)
+{
+ int *s, *d;
+
+ d = (int *)malloc(sizeof(int));
+ if (!d) return NULL;
+ s = (int *)src;
+ *d = *s;
+ CONV32(*d);
+ *size_ret = sizeof(int);
+ return d;
+}
+
+/* LONG LONG TYPE */
+static int
+eet_data_get_long_long(void *src, void *src_end, void *dst)
+{
+ long long *s, *d;
+ long long tmp;
+
+ if ((src + sizeof(long long)) > src_end) return -1;
+ s = (long long *)src;
+ d = (long long *)dst;
+ /* alignment fixup */
+ if ((int)s & (sizeof(long long) - 1))
+ {
+ memcpy(&tmp, s, sizeof(long long));
+ s = &tmp;
+ }
+ *d = *s;
+ CONV64(*d);
+ return sizeof(long long);
+}
+
+static void *
+eet_data_put_long_long(void *src, int *size_ret)
+{
+ long long *s, *d;
+
+ d = (long long *)malloc(sizeof(long long));
+ if (!d) return NULL;
+ s = (long long *)src;
+ *d = *s;
+ CONV64(*d);
+ *size_ret = sizeof(long long);
+ return d;
+}
+
+/* STRING TYPE */
+static int
+eet_data_get_string(void *src, void *src_end, void *dst)
+{
+ char *s, **d, *p;
+ int len;
+
+ s = (char *)src;
+ d = (char **)dst;
+ p = s;
+ len = 0;
+ while ((p < (char *)src_end) && (*p != 0)) {len++; p++;}
+ *d = malloc(len + 1);
+ if (!(*d)) return -1;
+ memcpy(*d, s, len);
+ (*d)[len] = 0;
+ return len + 1;
+}
+
+static void *
+eet_data_put_string(void *src, int *size_ret)
+{
+ char *s, *d;
+ int len;
+
+ if (!src) src = "";
+ s = (char *)(*((char **)src));
+ len = strlen(s);
+ d = malloc(len + 1);
+ if (!d) return NULL;
+ strcpy(d, s);
+ *size_ret = len + 1;
+ return d;
+}
+
+/* FLOAT TYPE */
+static int
+eet_data_get_float(void *src, void *src_end, void *dst)
+{
+ float *d;
+ char *s, *str, *p, *prev_locale;
+ int len;
+
+ s = (char *)src;
+ d = (float *)dst;
+ p = s;
+ len = 0;
+ while ((p < (char *)src_end) && (*p != 0)) {len++; p++;}
+ str = malloc(len + 1);
+ if (!str) return -1;
+ memcpy(str, s, len);
+ str[len] = 0;
+
+ prev_locale = setlocale(LC_NUMERIC, "C");
+ *d = (float)atof(str);
+ if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
+
+ free(str);
+ return len + 1;
+}
+
+static void *
+eet_data_put_float(void *src, int *size_ret)
+{
+ float *s;
+ char *d, buf[64], *prev_locale;
+ int len;
+
+ s = (float *)src;
+ prev_locale = setlocale(LC_NUMERIC, "C");
+ snprintf(buf, sizeof(buf), "%16.16f", (double)(*s));
+ if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
+ len = strlen(buf);
+ d = malloc(len + 1);
+ if (!d) return NULL;
+ strcpy(d, buf);
+ *size_ret = len + 1;
+ return d;
+}
+
+/* DOUBLE TYPE */
+static int
+eet_data_get_double(void *src, void *src_end, void *dst)
+{
+ double *d;
+ char *s, *str, *p, *prev_locale;
+ int len;
+
+ s = (char *)src;
+ d = (double *)dst;
+ p = s;
+ len = 0;
+ while ((p < (char *)src_end) && (*p != 0)) {len++; p++;}
+ str = malloc(len + 1);
+ if (!str) return -1;
+ memcpy(str, s, len);
+ str[len] = 0;
+
+ prev_locale = setlocale(LC_NUMERIC, "C");
+ *d = (double)atof(str);
+ if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
+
+ free(str);
+ return len + 1;
+}
+
+static void *
+eet_data_put_double(void *src, int *size_ret)
+{
+ double *s;
+ char *d, buf[128], *prev_locale;
+ int len;
+
+ s = (double *)src;
+ prev_locale = setlocale(LC_NUMERIC, "C");
+ snprintf(buf, sizeof(buf), "%32.32f", (double)(*s));
+ if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
+ len = strlen(buf);
+ d = malloc(len + 1);
+ if (!d) return NULL;
+ strcpy(d, buf);
+ *size_ret = len + 1;
+ return d;
+}
+
+static int
+eet_data_get_type(int type, void *src, void *src_end, void *dest)
+{
+ int ret;
+
+ ret = eet_coder[type - 1].get(src, src_end, dest);
+ return ret;
+}
+
+static void *
+eet_data_put_type(int type, void *src, int *size_ret)
+{
+ void *ret;
+
+ ret = eet_coder[type - 1].put(src, size_ret);
+ return ret;
+}
+
+/* chunk format...
+ *
+ * char[4] = "CHnK";
+ * int = chunk size (including magic string);
+ * char[] = chuck magic/name string (0 byte terminated);
+ * ... sub-chunks (a chunk can contain chuncks recusrively) ...
+ * or
+ * ... payload data ...
+ *
+ */
+
+static Eet_Data_Chunk *
+eet_data_chunk_get(void *src, int size)
+{
+ Eet_Data_Chunk *chnk;
+ char *s;
+ int ret1, ret2;
+
+ if (!src) return NULL;
+ if (size <= 8) return NULL;
+
+ chnk = calloc(1, sizeof(Eet_Data_Chunk));
+ if (!chnk) return NULL;
+
+ s = src;
+ if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'n') || (s[3] != 'K'))
+ {
+ free(chnk);
+ return NULL;
+ }
+ ret1 = eet_data_get_type(EET_T_INT, (void *)(s + 4), (void *)(s + size), &(chnk->size));
+ if (ret1 <= 0)
+ {
+ free(chnk);
+ return NULL;
+ }
+ if ((chnk->size < 0) || ((chnk->size + 8) > size))
+ {
+ free(chnk);
+ return NULL;
+ }
+ ret2 = eet_data_get_type(EET_T_STRING, (void *)(s + 8), (void *)(s + size), &(chnk->name));
+ if (ret2 <= 0)
+ {
+ free(chnk);
+ return NULL;
+ }
+ chnk->data = src + 4 + ret1 + ret2;
+ chnk->size -= ret2;
+ return chnk;
+}
+
+static Eet_Data_Chunk *
+eet_data_chunk_new(void *data, int size, char *name)
+{
+ Eet_Data_Chunk *chnk;
+
+ if (!name) return NULL;
+ chnk = calloc(1, sizeof(Eet_Data_Chunk));
+ if (!chnk) return NULL;
+
+ chnk->name = strdup(name);
+ chnk->size = size;
+ chnk->data = data;
+
+ return chnk;
+}
+
+static void
+eet_data_chunk_free(Eet_Data_Chunk *chnk)
+{
+ if (chnk->name) free(chnk->name);
+ free(chnk);
+}
+
+static Eet_Data_Stream *
+eet_data_stream_new(void)
+{
+ Eet_Data_Stream *ds;
+
+ ds = calloc(1, sizeof(Eet_Data_Stream));
+ if (!ds) return NULL;
+ return ds;
+}
+
+static void
+eet_data_stream_free(Eet_Data_Stream *ds)
+{
+ if (ds->data) free(ds->data);
+ free(ds);
+}
+
+static void
+eet_data_stream_write(Eet_Data_Stream *ds, void *data, int size)
+{
+ char *p;
+
+ if ((ds->pos + size) > ds->size)
+ {
+ ds->data = realloc(ds->data, ds->size + size + 256);
+ if (!ds->data)
+ {
+ ds->pos = 0;
+ ds->size = 0;
+ return;
+ }
+ ds->size = ds->size + size + 256;
+ }
+ p = ds->data;
+ memcpy(p + ds->pos, data, size);
+ ds->pos += size;
+}
+
+static void
+eet_data_chunk_put(Eet_Data_Chunk *chnk, Eet_Data_Stream *ds)
+{
+ int *size;
+ int s;
+ int size_ret;
+
+ if (!chnk->data) return;
+ /* chunk head */
+ eet_data_stream_write(ds, "CHnK", 4);
+ /* size of chunk payload data + name */
+ s = strlen(chnk->name) + 1 + chnk->size;
+ size = eet_data_put_int(&s, &size_ret);
+ if (size)
+ {
+ eet_data_stream_write(ds, size, size_ret);
+ free(size);
+ }
+ /* write chunk name */
+ eet_data_stream_write(ds, chnk->name, strlen(chnk->name) + 1);
+ /* write payload */
+ eet_data_stream_write(ds, chnk->data, chnk->size);
+}
+
+/*---*/
+
+int
+eet_data_image_write(Eet_File *ef, char *name,
+ void *data, int w, int h, int alpha,
+ int compress, int quality, int lossy)
+{
+ void *d = NULL;
+ int size = 0;
+
+ d = eet_data_image_encode(data, &size, w, h, alpha, compress, quality, lossy);
+ if (d)
+ {
+ int v;
+
+ v = eet_write(ef, name, d, size, 0);
+ free(d);
+ return v;
+ }
+ return 0;
+}
+
+void *
+eet_data_image_read(Eet_File *ef, char *name,
+ int *w, int *h, int *alpha,
+ int *compress, int *quality, int *lossy)
+{
+ void *data;
+ int size;
+ unsigned int *d = NULL;
+ int header[8];
+
+ data = eet_read(ef, name, &size);
+ if (!data) return NULL;
+ d = eet_data_image_decode(data, size, w, h, alpha, compress, quality, lossy);
+ free(data);
+ return d;
+}
+
+void *
+eet_data_image_encode(void *data, int *size_ret, int w, int h, int alpha, int compress, int quality, int lossy)
+{
+ void *d = NULL;
+ int size = 0;
+
+ if (lossy == 0)
+ {
+ if (compress <= 0)
+ d = eet_data_image_lossless_convert(&size, data, w, h, alpha);
+ else
+ d = eet_data_image_lossless_compressed_convert(&size, data, w, h, alpha, compress);
+ }
+ 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 (size_ret) *size_ret = size;
+ return d;
+}
+
+void *
+eet_data_image_decode(void *data, int size, int *w, int *h, int *alpha, int *compress, int *quality, int *lossy)
+{
+ unsigned int *d = NULL;
+ int header[8];
+
+ if (words_bigendian == -1)
+ {
+ unsigned long int v;
+
+ v = htonl(0x12345678);
+ if (v == 0x12345678) words_bigendian = 1;
+ else words_bigendian = 0;
+ }
+
+ if (size < 32) return NULL;
+
+ memcpy(header, data, 32);
+ if (words_bigendian)
+ {
+ int i;
+
+ for (i = 0; i < 8; i++) SWAP32(header[i]);
+ }
+ if (header[0] == 0xac1dfeed)
+ {
+ int iw, ih, al, cp;
+ unsigned int *body;
+
+ iw = header[1];
+ ih = header[2];
+ al = header[3];
+ cp = header[4];
+ if ((iw > 8192) || (ih > 8192)) return NULL;
+ if ((cp == 0) && (size < ((iw * ih * 4) + 32))) return NULL;
+ body = ((unsigned int *)data) + 8;
+ d = malloc(iw * ih * 4);
+ if (!d) return NULL;
+ if (!cp)
+ {
+ memcpy(d, body, iw * ih * 4);
+ if (words_bigendian)
+ {
+ int x;
+
+ for (x = 0; x < (iw * ih); x++) SWAP32(d[x]);
+ }
+ }
+ else
+ {
+ uLongf dlen;
+
+ dlen = iw * ih * 4;
+ uncompress((Bytef *)d, &dlen, (Bytef *)body,
+ (uLongf)(size - 32));
+ if (words_bigendian)
+ {
+ int x;
+
+ for (x = 0; x < (iw * ih); x++) SWAP32(d[x]);
+ }
+ }
+ if (d)
+ {
+ if (w) *w = iw;
+ if (h) *h = ih;
+ if (alpha) *alpha = al;
+ if (compress) *compress = cp;
+ if (lossy) *lossy = 0;
+ if (quality) *quality = 100;
+ }
+ }
+ else if (header[0] == 0xbeeff00d)
+ {
+ int iw = 0, ih = 0;
+ int sz1, sz2;
+ unsigned char *dt;
+
+ sz1 = header[1];
+ sz2 = header[2];
+ dt = data;
+ dt += 12;
+ d = eet_data_image_jpeg_rgb_decode(dt, sz1, &iw, &ih);
+ if (d)
+ {
+ dt += sz1;
+ eet_data_image_jpeg_alpha_decode(dt, sz2, d, &iw, &ih);
+ }
+ if (d)
+ {
+ if (w) *w = iw;
+ if (h) *h = ih;
+ if (alpha) *alpha = 1;
+ if (compress) *compress = 0;
+ if (lossy) *lossy = 1;
+ if (quality) *quality = 75;
+ }
+ }
+ else
+ {
+ int iw = 0, ih = 0;
+
+ d = eet_data_image_jpeg_rgb_decode(data, size, &iw, &ih);
+ if (d)
+ {
+ 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 d;
+}
+
+Eet_Data_Descriptor *
+eet_data_descriptor_new(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_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))
+{
+ Eet_Data_Descriptor *edd;
+
+ edd = calloc(1, sizeof(Eet_Data_Descriptor));
+ edd->name = strdup(name);
+ edd->size = size;
+ edd->func.list_next = func_list_next;
+ edd->func.list_append = func_list_append;
+ edd->func.list_data = func_list_data;
+ edd->func.hash_foreach = func_hash_foreach;
+ edd->func.hash_add = func_hash_add;
+ return edd;
+}
+
+void
+eet_data_descriptor_free(Eet_Data_Descriptor *edd)
+{
+ int i;
+
+ if (edd->name) free(edd->name);
+ for (i = 0; i < edd->elements.num; i++)
+ {
+ if (edd->elements.set[i].name) free(edd->elements.set[i].name);
+ if (edd->elements.set[i].counter_name) free(edd->elements.set[i].counter_name);
+ }
+ if (edd->elements.set) free(edd->elements.set);
+ free(edd);
+}
+
+void
+eet_data_descriptor_element_add(Eet_Data_Descriptor *edd, char *name, int type,
+ int group_type,
+ int offset,
+ int count, char *counter_name,
+ Eet_Data_Descriptor *subtype)
+{
+ Eet_Data_Element *ede;
+
+ edd->elements.num++;
+ edd->elements.set = realloc(edd->elements.set, edd->elements.num * sizeof(Eet_Data_Element));
+ if (!edd->elements.set) return;
+ ede = &(edd->elements.set[edd->elements.num - 1]);
+ ede->name = strdup(name);
+ ede->type = type;
+ ede->group_type = group_type;
+ ede->offset = offset;
+ ede->count = count;
+ if (counter_name)
+ ede->counter_name = strdup(counter_name);
+ else ede->counter_name = NULL;
+ ede->subtype = subtype;
+}
+
+void *
+eet_data_read(Eet_File *ef, Eet_Data_Descriptor *edd, char *name)
+{
+ void *data_dec;
+ void *data;
+ int size;
+
+ data = eet_read(ef, name, &size);
+ if (!data) return NULL;
+ data_dec = eet_data_descriptor_decode(edd, data, size);
+ free(data);
+ return data_dec;
+}
+
+int
+eet_data_write(Eet_File *ef, Eet_Data_Descriptor *edd, char *name, void *data, int compress)
+{
+ void *data_enc;
+ int size;
+ int val;
+
+ data_enc = eet_data_descriptor_encode(edd, data, &size);
+ if (!data_enc) return 0;
+ val = eet_write(ef, name, data_enc, size, compress);
+ free(data_enc);
+ return val;
+}
+
+void *
+eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
+ void *data_in,
+ int size_in)
+{
+ void *data;
+ char *p;
+ int size;
+ Eet_Data_Chunk *chnk;
+
+ if (words_bigendian == -1)
+ {
+ unsigned long int v;
+
+ v = htonl(0x12345678);
+ if (v == 0x12345678) words_bigendian = 1;
+ else words_bigendian = 0;
+ }
+
+ data = calloc(1, edd->size);
+ if (!data) return NULL;
+ chnk = eet_data_chunk_get(data_in, size_in);
+ if (!chnk)
+ {
+ free(data);
+ return NULL;
+ }
+ if (strcmp(chnk->name, edd->name))
+ {
+ eet_data_chunk_free(chnk);
+ free(data);
+ return NULL;
+ }
+ p = chnk->data;
+ size = size_in - (4 + 4 + strlen(chnk->name) + 1);
+ while (size > 0)
+ {
+ Eet_Data_Chunk *echnk;
+ int i;
+
+ /* get next data chunk */
+ echnk = eet_data_chunk_get(p, size);
+ if (!echnk)
+ {
+ /* FIXME: partially built data struct - leak!!!! */
+ free(data);
+ eet_data_chunk_free(chnk);
+ return NULL;
+ }
+ for (i = 0; i < edd->elements.num; i++)
+ {
+ Eet_Data_Element *ede;
+
+ ede = &(edd->elements.set[i]);
+ if (!strcmp(echnk->name, ede->name))
+ {
+ if (ede->group_type == EET_G_UNKNOWN)
+ {
+ int ret;
+ void *data_ret;
+
+ if ((ede->type >= EET_T_CHAR) &&
+ (ede->type <= EET_T_STRING))
+ {
+ ret = eet_data_get_type(ede->type,
+ echnk->data,
+ ((char *)echnk->data) + echnk->size,
+ ((char *)data) + ede->offset);
+ }
+ else if (ede->subtype)
+ {
+ void **ptr;
+
+ data_ret = eet_data_descriptor_decode(ede->subtype,
+ echnk->data,
+ echnk->size);
+ ptr = (void **)(((char *)data) + ede->offset);
+ *ptr = (void *)data_ret;
+ }
+ }
+ else
+ {
+ switch (ede->group_type)
+ {
+ case EET_G_ARRAY:
+ case EET_G_VAR_ARRAY:
+ {
+ printf("ARRAY TYPE NOT IMPLIMENTED YET!!!\n");
+ }
+ break;
+ case EET_G_LIST:
+ {
+ int ret;
+ void *list = NULL;
+ void **ptr;
+ void *data_ret;
+
+ ptr = (void **)(((char *)data) + ede->offset);
+ list = *ptr;
+ data_ret = NULL;
+ if ((ede->type >= EET_T_CHAR) &&
+ (ede->type <= EET_T_STRING))
+ {
+ data_ret = calloc(1, eet_coder[ede->type].size);
+ if (data_ret)
+ {
+ ret = eet_data_get_type(ede->type,
+ echnk->data,
+ ((char *)echnk->data) + echnk->size,
+ data_ret);
+ if (ret <= 0)
+ {
+ free(data_ret);
+ data_ret = NULL;
+ }
+ }
+ }
+ else if (ede->subtype)
+ {
+ data_ret = eet_data_descriptor_decode(ede->subtype,
+ echnk->data,
+ echnk->size);
+ }
+ if (data_ret)
+ {
+ list = edd->func.list_append(list, data_ret);
+ *ptr = list;
+ }
+ }
+ break;
+ case EET_G_HASH:
+ printf("HASH TYPE NOT IMPLIMENTED YET!!!\n");
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ }
+ /* advance to next chunk */
+ p += (4 + 4 + strlen(echnk->name) + 1 + echnk->size);
+ size -= (4 + 4 + strlen(echnk->name) + 1 + echnk->size);
+ eet_data_chunk_free(echnk);
+ }
+ eet_data_chunk_free(chnk);
+ return data;
+}
+
+void *
+eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
+ void *data_in,
+ int *size_ret)
+{
+ Eet_Data_Chunk *chnk;
+ Eet_Data_Stream *ds;
+ int i;
+ void *cdata;
+ int csize;
+
+ if (words_bigendian == -1)
+ {
+ unsigned long int v;
+
+ v = htonl(0x12345678);
+ if (v == 0x12345678) words_bigendian = 1;
+ else words_bigendian = 0;
+ }
+
+ ds = eet_data_stream_new();
+ for (i = 0; i < edd->elements.num; i++)
+ {
+ Eet_Data_Element *ede;
+ Eet_Data_Chunk *echnk;
+ void *data;
+ int size;
+
+ ede = &(edd->elements.set[i]);
+ data = NULL;
+ if (ede->group_type == EET_G_UNKNOWN)
+ {
+ if ((ede->type >= EET_T_CHAR) &&
+ (ede->type <= EET_T_STRING))
+ data = eet_data_put_type(ede->type,
+ ((char *)data_in) + ede->offset,
+ &size);
+ else if (ede->subtype)
+ data = eet_data_descriptor_encode(ede->subtype,
+ *((char **)(((char *)data_in) + ede->offset)),
+ &size);
+ if (data)
+ {
+ echnk = eet_data_chunk_new(data, size, ede->name);
+ eet_data_chunk_put(echnk, ds);
+ eet_data_chunk_free(echnk);
+ free(data);
+ data = NULL;
+ }
+ }
+ else
+ {
+ switch (ede->group_type)
+ {
+ case EET_G_ARRAY:
+ case EET_G_VAR_ARRAY:
+ {
+ printf("ARRAY TYPE NOT IMPLIMENTED YET!!!\n");
+ }
+ break;
+ case EET_G_LIST:
+ {
+ void *l;
+
+ l = *((void **)(((char *)data_in) + ede->offset));
+ for (; l; l = edd->func.list_next(l))
+ {
+ if ((ede->type >= EET_T_CHAR) &&
+ (ede->type <= EET_T_STRING))
+ data = eet_data_put_type(ede->type,
+ edd->func.list_data(l),
+ &size);
+ else if (ede->subtype)
+ data = eet_data_descriptor_encode(ede->subtype,
+ edd->func.list_data(l),
+ &size);
+ if (data)
+ {
+ echnk = eet_data_chunk_new(data, size, ede->name);
+ eet_data_chunk_put(echnk, ds);
+ eet_data_chunk_free(echnk);
+ free(data);
+ data = NULL;
+ }
+ }
+ }
+ break;
+ case EET_G_HASH:
+ {
+ printf("HASH TYPE NOT IMPLIMENTED YET!!!\n");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ chnk = eet_data_chunk_new(ds->data, ds->pos, edd->name);
+ ds->data = NULL;
+ ds->size = 0;
+ eet_data_stream_free(ds);
+
+ ds = eet_data_stream_new();
+ eet_data_chunk_put(chnk, ds);
+ cdata = ds->data;
+ csize = ds->pos;
+
+ ds->data = NULL;
+ ds->size = 0;
+ eet_data_stream_free(ds);
+ *size_ret = csize;
+ eet_data_chunk_free(chnk);
+
+ return cdata;
+}
--- /dev/null
+#include "Eet.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <zlib.h>
+#include <string.h>
+#include <fnmatch.h>
+
+#define EET_MAGIC_FILE 0x1ee7ff00
+#define EET_MAGIC_FILE_HEADER 0x1ee7ff01
+#define EET_MAGIC_FILE_NODE 0x1ee7ff02
+#define EET_MAGIC_FILE_DIRECTORY 0x1ee7ff03
+#define EET_MAGIC_FILE_DIRECTORY_HASH 0x1ee7ff04
+
+typedef struct _Eet_File_Header Eet_File_Header;
+typedef struct _Eet_File_Node Eet_File_Node;
+typedef struct _Eet_File_Directory Eet_File_Directory;
+typedef struct _Eet_File_Directory_Hash Eet_File_Directory_Hash;
+
+struct _Eet_File
+{
+ int magic;
+ int references;
+
+ char *path;
+ char *real_path;
+
+ FILE *fp;
+ Eet_File_Mode mode;
+
+ int writes_pending : 1;
+
+ Eet_File_Header *header;
+};
+struct _Eet_File_Header
+{
+ int magic;
+ Eet_File_Directory *directory;
+};
+struct _Eet_File_Node
+{
+ char *name;
+ int offset;
+ int compression;
+ int size;
+ int data_size;
+ void *data;
+};
+struct _Eet_File_Directory
+{
+ int size;
+ Eet_File_Directory_Hash *hash;
+};
+struct _Eet_File_Directory_Hash
+{
+ int size;
+ Eet_File_Node *node;
+};
+
+#if 0
+/* 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) */
+} directory[num_directory_entries];
+/* and now startes the data stream... */
+#endif
+
+/* prototypes of internal calls */
+static Eet_File *eet_cache_find(char *real_path, Eet_File **cache, int cache_num);
+static void eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num);
+static void eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num);
+static int eet_string_match(char *s1, char *s2);
+static int eet_hash_gen(char *key, int hash_size);
+static void eet_flush(Eet_File *ef);
+
+/* cache. i don't expect this to ever be large, so arrays will do */
+static int eet_writers_num = 0;
+static Eet_File **eet_writers = NULL;
+static int eet_readers_num = 0;
+static Eet_File **eet_readers = NULL;
+
+/* find an eet file in the currently in use cache */
+static Eet_File *
+eet_cache_find(char *real_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]->real_path, real_path)) return cache[i];
+ }
+ /* not found */
+ return NULL;
+}
+
+/* add to end of cache */
+static void
+eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num)
+{
+ Eet_File **new_cache;
+ int new_cache_num;
+
+ new_cache_num = *cache_num;
+ new_cache = *cache;
+ new_cache_num++;
+ new_cache = realloc(new_cache, new_cache_num * sizeof(Eet_File *));
+ if (!new_cache) return;
+ new_cache[new_cache_num - 1] = ef;
+ *cache = new_cache;
+ *cache_num = new_cache_num;
+}
+
+/* delete from cache */
+static void
+eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num)
+{
+ Eet_File **new_cache;
+ int new_cache_num;
+ int i, j;
+
+ new_cache_num = *cache_num;
+ new_cache = *cache;
+ if (new_cache_num <= 0) return;
+ for (i = 0; i < new_cache_num; i++)
+ {
+ if (new_cache[i] == ef) break;
+ }
+ if (i >= new_cache_num) return;
+ new_cache_num--;
+ for (j = i; j < new_cache_num; j++) new_cache[j] = new_cache[j + 1];
+ new_cache = realloc(new_cache, new_cache_num * sizeof(Eet_File *));
+ *cache_num = new_cache_num;
+ if ((new_cache_num > 0) && (!new_cache)) return;
+ *cache = new_cache;
+}
+
+/* internal string match. bails out at first mismatch - not comparing all */
+/* bytes in strings */
+static int
+eet_string_match(char *s1, char *s2)
+{
+ /* both null- no match */
+ if ((!s1) || (!s2)) return 0;
+ /* go thru - first mismatch - exit with 0 */
+ do
+ {
+ if (*s1 != *s2) return 0;
+ s1++;
+ s2++;
+ }
+ while ((*s1) || (*s2));
+ /* got this far. match */
+ return 1;
+}
+
+/* caluclate hash table entry valu with bitmask size of hash_size */
+static int
+eet_hash_gen(char *key, int hash_size)
+{
+ int hash_num = 0;
+ unsigned char *ptr;
+ const int masks[9] =
+ {
+ 0x00,
+ 0x01,
+ 0x03,
+ 0x07,
+ 0x0f,
+ 0x1f,
+ 0x3f,
+ 0x7f,
+ 0xff
+ };
+
+ /* no string - index 0 */
+ if (!key) return 0;
+
+ /* calc hash num */
+ for (ptr = key; *ptr; ptr++) hash_num ^= (int)(*ptr);
+
+ /* mask it */
+ hash_num &= masks[hash_size];
+ /* return it */
+ return hash_num;
+}
+
+/* flush out writes to an eet file */
+static void
+eet_flush(Eet_File *ef)
+{
+ int i, j, count, size, num, offset;
+ int head[3];
+ unsigned long int i1, i2;
+
+ /* check to see its' an eet file pointer */
+ if ((!ef) || (ef->magic != EET_MAGIC_FILE))
+ return;
+ if (ef->mode != EET_FILE_MODE_WRITE) return;
+ if (!ef->writes_pending) return;
+
+ /* calculate total size in bytes of directory block */
+ size = 0;
+ count = 0;
+ num = (1 << (ef->header->directory->size - 1));
+ for (i = 0; i < num; i++)
+ {
+ for (j = 0; j < ef->header->directory->hash[i].size; j++)
+ {
+ size += 20 + strlen(ef->header->directory->hash[i].node[j].name);
+ count++;
+ }
+ }
+ /* caluclate offsets per entry */
+ offset = 0;
+ for (i = 0; i < num; i++)
+ {
+ for (j = 0; j < ef->header->directory->hash[i].size; j++)
+ {
+ ef->header->directory->hash[i].node[j].offset = 12 + size + offset;
+ offset += ef->header->directory->hash[i].node[j].size;
+ }
+ }
+ /* go thru and write the header */
+ i1 = (unsigned long int)EET_MAGIC_FILE;
+ i2 = htonl(i1);
+ head[0] = (int)i2;
+ i1 = (unsigned long int)count;
+ i2 = htonl(i1);
+ head[1] = (int)i2;
+ i1 = (unsigned long int)size;
+ i2 = htonl(i1);
+ head[2] = (int)i2;
+ fseek(ef->fp, 0, SEEK_SET);
+ if (fwrite(head, 12, 1, ef->fp) != 1) return;
+ offset = 12;
+ for (i = 0; i < num; i++)
+ {
+ for (j = 0; j < ef->header->directory->hash[i].size; j++)
+ {
+ unsigned char *buf;
+ int buf_size;
+ int name_size;
+
+ name_size = strlen(ef->header->directory->hash[i].node[j].name);
+ buf_size = 20 + name_size;
+ buf = malloc(buf_size);
+ if (!buf) return;
+ i1 = (unsigned long int)ef->header->directory->hash[i].node[j].offset;
+ i2 = htonl(i1);
+ *((int *)(buf + 0)) = (int)i2;
+ i1 = (unsigned long int)ef->header->directory->hash[i].node[j].compression;
+ i2 = htonl(i1);
+ *((int *)(buf + 4)) = (int)i2;
+ i1 = (unsigned long int)ef->header->directory->hash[i].node[j].size;
+ i2 = htonl(i1);
+ *((int *)(buf + 8)) = (int)i2;
+ i1 = (unsigned long int)ef->header->directory->hash[i].node[j].data_size;
+ i2 = htonl(i1);
+ *((int *)(buf + 12)) = (int)i2;
+ i1 = (unsigned long int)name_size;
+ i2 = htonl(i1);
+ *((int *)(buf + 16)) = (int)i2;
+ memcpy(buf + 20, ef->header->directory->hash[i].node[j].name, name_size);
+ if (fwrite(buf, buf_size, 1, ef->fp) != 1)
+ {
+ free(buf);
+ return;
+ }
+ offset += buf_size;
+ free(buf);
+ }
+ }
+ /* write data */
+ for (i = 0; i < num; i++)
+ {
+ for (j = 0; j < ef->header->directory->hash[i].size; j++)
+ {
+ if (fwrite(ef->header->directory->hash[i].node[j].data,
+ ef->header->directory->hash[i].node[j].size,
+ 1, ef->fp) != 1)
+ return;
+ }
+ }
+ /* no more writes pending */
+ ef->writes_pending = 0;
+}
+
+Eet_File *
+eet_open(char *file, Eet_File_Mode mode)
+{
+ Eet_File *ef;
+ char buf[PATH_MAX];
+
+ /* in case this is a symlink... find out where it REALLY points */
+ if (!realpath(file, buf))
+ {
+ if (mode == EET_FILE_MODE_READ) return NULL;
+ }
+
+ /* find the current file handle in cache*/
+ ef = NULL;
+ if (mode == EET_FILE_MODE_READ)
+ ef = eet_cache_find(buf, eet_readers, eet_readers_num);
+ else if (mode == EET_FILE_MODE_WRITE)
+ ef = eet_cache_find(buf, eet_writers, eet_writers_num);
+ /* we found one */
+ if (ef)
+ {
+ /* reference it up and return it */
+ ef->references++;
+ return ef;
+ }
+
+ /* allocate struct for eet file and have it zero'd out */
+ ef = calloc(sizeof(Eet_File), 1);
+ if (!ef) return NULL;
+
+ /* fill some of the members */
+ ef->path = strdup(file);
+ ef->real_path = strdup(buf);
+ ef->magic = EET_MAGIC_FILE;
+ ef->references = 1;
+ ef->mode = mode;
+
+ /* try open the file based on mode */
+ if (ef->mode == EET_FILE_MODE_READ)
+ ef->fp = fopen(ef->path, "r");
+ else if (ef->mode == EET_FILE_MODE_WRITE)
+ {
+ /* opening for write - delete old copy of file right away */
+ unlink(ef->real_path);
+ ef->fp = fopen(ef->path, "w");
+ }
+ else
+ {
+ eet_close(ef);
+ return NULL;
+ }
+
+ /* if we can't open - bail out */
+ if (!ef->fp)
+ {
+ eet_close(ef);
+ return NULL;
+ }
+
+ /* if we opened for read */
+ if (mode == EET_FILE_MODE_READ)
+ {
+ unsigned char buf[12];
+ unsigned char *dyn_buf, *p;
+ unsigned long int i1, i2;
+ int num_entries, byte_entries, i;
+ size_t count;
+
+ /* build header table if read mode */
+ /* geat header */
+ count = fread(buf, 12, 1, ef->fp);
+ if (count != 1)
+ {
+ eet_close(ef);
+ return NULL;
+ }
+ /* get magic no */
+ i1 = *((int *)(buf + 0));
+ i2 = ntohl(i1);
+ if (i2 != EET_MAGIC_FILE)
+ {
+ eet_close(ef);
+ return NULL;
+ }
+ /* get entries count and byte count */
+ i1 = *((int *)(buf + 4));
+ i2 = ntohl(i1);
+ num_entries = (int)i2;
+ i1 = *((int *)(buf + 8));
+ i2 = ntohl(i1);
+ byte_entries = (int)i2;
+ /* we cant have <= 0 values here - invalid */
+ if ((num_entries <= 0) || (byte_entries <= 0))
+ {
+ eet_close(ef);
+ return NULL;
+ }
+ /* we can't have more entires than minimum bytes for those! invalid! */
+ if ((num_entries * 20) > byte_entries)
+ {
+ eet_close(ef);
+ return NULL;
+ }
+ /* allocate dynamic buffer for entire directory block */
+ dyn_buf = malloc(byte_entries);
+ if (!dyn_buf)
+ {
+ eet_close(ef);
+ return NULL;
+ }
+ /* allocate header */
+ ef->header = calloc(sizeof(Eet_File_Header), 1);
+ if (!ef->header)
+ {
+ free(dyn_buf);
+ eet_close(ef);
+ return NULL;
+ }
+ ef->header->magic = EET_MAGIC_FILE_HEADER;
+ /* allocate directory block in ram */
+ ef->header->directory = calloc(sizeof(Eet_File_Directory), 1);
+ if (!ef->header->directory)
+ {
+ free(dyn_buf);
+ eet_close(ef);
+ return NULL;
+ }
+ /* 8 bit hash table (256 buckets) */
+ ef->header->directory->size = 8;
+ /* allocate base hash table */
+ ef->header->directory->hash = calloc(sizeof(Eet_File_Directory_Hash), (1 << (ef->header->directory->size - 1)));
+ if (!ef->header->directory->hash)
+ {
+ free(dyn_buf);
+ eet_close(ef);
+ return NULL;
+ }
+ /* actually read the directory block - all of it, into ram */
+ count = fread(dyn_buf, byte_entries, 1, ef->fp);
+ if (count != 1)
+ {
+ free(dyn_buf);
+ eet_close(ef);
+ return NULL;
+ }
+ /* parse directory block */
+ p = dyn_buf;
+ for (i = 0; i < num_entries; i++)
+ {
+ int offset;
+ int flags;
+ int size;
+ int data_size;
+ int name_size;
+ char *name;
+ int hash;
+ Eet_File_Node *node;
+ int node_size;
+
+ /* out directory block is inconsistent - we have oveerun our */
+ /* dynamic block buffer before we finished scanning dir entries */
+ if (p >= (dyn_buf + byte_entries))
+ {
+ free(dyn_buf);
+ eet_close(ef);
+ return NULL;
+ }
+ /* get entrie header */
+ i1 = *((int *)(p + 0));
+ i2 = ntohl(i1);
+ offset = (int)i2;
+ i1 = *((int *)(p + 4));
+ i2 = ntohl(i1);
+ flags = (int)i2;
+ i1 = *((int *)(p + 8));
+ i2 = ntohl(i1);
+ size = (int)i2;
+ i1 = *((int *)(p + 12));
+ i2 = ntohl(i1);
+ data_size = (int)i2;
+ i1 = *((int *)(p + 16));
+ i2 = ntohl(i1);
+ name_size = (int)i2;
+ /* invalid size */
+ if (size <= 0)
+ {
+ free(dyn_buf);
+ eet_close(ef);
+ return NULL;
+ }
+ /* invalid name_size */
+ if (name_size <= 0)
+ {
+ free(dyn_buf);
+ eet_close(ef);
+ return NULL;
+ }
+ /* reading name would mean falling off end of dyn_buf - invalid */
+ if ((p + 16 + name_size) > (dyn_buf + byte_entries))
+ {
+ free(dyn_buf);
+ eet_close(ef);
+ return NULL;
+ }
+ /* allocate name string */
+ name = malloc(name_size + 1);
+ if (!name)
+ {
+ free(dyn_buf);
+ eet_close(ef);
+ return NULL;
+ }
+ /* copy name in and terminate it */
+ strncpy(name, p + 20, name_size);
+ name[name_size] = 0;
+
+ /* get hask bucket it should go in */
+ hash = eet_hash_gen(name, ef->header->directory->size);
+ /* resize hask bucket */
+ node = realloc(ef->header->directory->hash[hash].node,
+ (ef->header->directory->hash[hash].size + 1) *
+ sizeof(Eet_File_Node));
+ if (!node)
+ {
+ free(dyn_buf);
+ eet_close(ef);
+ return NULL;
+ }
+ /* current node size */
+ node_size = ef->header->directory->hash[hash].size;
+ /* resized node list set up */
+ ef->header->directory->hash[hash].node = node;
+ /* new node at end */
+ ef->header->directory->hash[hash].node[node_size].name = name;
+ ef->header->directory->hash[hash].node[node_size].offset = offset;
+ ef->header->directory->hash[hash].node[node_size].compression = flags;
+ ef->header->directory->hash[hash].node[node_size].size = size;
+ ef->header->directory->hash[hash].node[node_size].data_size = data_size;
+ /* currently we have no data loaded */
+ ef->header->directory->hash[hash].node[node_size].data = NULL;
+ /* increment number of nodes */
+ ef->header->directory->hash[hash].size++;
+ /* advance */
+ p += 20 + name_size;
+ }
+ /* done - free dynamic buffer */
+ free(dyn_buf);
+ }
+ /* add to cache */
+ if (ef->mode == EET_FILE_MODE_READ)
+ eet_cache_add(ef, &eet_readers, &eet_readers_num);
+ else if (ef->mode == EET_FILE_MODE_WRITE)
+ eet_cache_add(ef, &eet_writers, &eet_writers_num);
+ return ef;
+}
+
+void
+eet_close(Eet_File *ef)
+{
+ /* check to see its' an eet file pointer */
+ if ((!ef) || (ef->magic != EET_MAGIC_FILE))
+ return;
+ /* deref */
+ ef->references--;
+ /* if its still referenced - dont go any further */
+ if (ef->references > 0) return;
+ /* remove from cache */
+ if (ef->mode == EET_FILE_MODE_READ)
+ eet_cache_del(ef, &eet_readers, &eet_readers_num);
+ else if (ef->mode == EET_FILE_MODE_WRITE)
+ eet_cache_del(ef, &eet_writers, &eet_writers_num);
+ /* flush any writes */
+ eet_flush(ef);
+
+ /* free up members */
+ if (ef->fp) fclose(ef->fp);
+ if (ef->path) free(ef->path);
+ if (ef->real_path) free(ef->real_path);
+
+ /* free up data */
+ if (ef->header)
+ {
+ if (ef->header->directory)
+ {
+ if (ef->header->directory->hash)
+ {
+ int i, num;
+
+ num = (1 << (ef->header->directory->size - 1));
+ for (i = 0; i < num; i++)
+ {
+ if (ef->header->directory->hash[i].node)
+ {
+ int j;
+ int num2;
+
+ num2 = ef->header->directory->hash[i].size;
+ for (j = 0; j < num2; j++)
+ {
+ if (ef->header->directory->hash[i].node[j].name)
+ free(ef->header->directory->hash[i].node[j].name);
+ if (ef->header->directory->hash[i].node[j].data)
+ free(ef->header->directory->hash[i].node[j].data);
+ }
+ free(ef->header->directory->hash[i].node);
+ }
+ }
+ free(ef->header->directory->hash);
+ }
+ free(ef->header->directory);
+ }
+ free(ef->header);
+ }
+
+ /* zero out ram for struct - caution tactic against stale memory use */
+ memset(ef, 0, sizeof(Eet_File));
+ /* free it */
+ free(ef);
+}
+
+void *
+eet_read(Eet_File *ef, char *name, int *size_ret)
+{
+ void *data = NULL;
+ int size = 0, tmp_size;
+ int hash, i, num;
+
+ /* check to see its' an eet file pointer */
+ if ((!ef) || (ef->magic != EET_MAGIC_FILE))
+ {
+ if (size_ret) *size_ret = 0;
+ return NULL;
+ }
+ /* get hash bucket this should be in */
+ hash = eet_hash_gen(name, ef->header->directory->size);
+ /* hunt hash bucket */
+ num = ef->header->directory->hash[hash].size;
+ for (i = 0; i < num; i++)
+ {
+ /* if it matches */
+ if (eet_string_match(ef->header->directory->hash[hash].node[i].name, name))
+ {
+ /* uncompressed data */
+ if (ef->header->directory->hash[hash].node[i].compression == 0)
+ {
+ /* get size */
+ size = ef->header->directory->hash[hash].node[i].size;
+ /* allocate data */
+ data = malloc(size);
+ if (data)
+ {
+ /* if we alreayd have the data in ram... copy that */
+ if (ef->header->directory->hash[hash].node[i].data)
+ memcpy(data,
+ ef->header->directory->hash[hash].node[i].data,
+ ef->header->directory->hash[hash].node[i].size);
+ /* or get data from disk */
+ else
+ {
+ /* seek to data location */
+ if (fseek(ef->fp, ef->header->directory->hash[hash].node[i].offset, SEEK_SET) < 0)
+ {
+ free(data);
+ data = NULL;
+ break;
+ }
+ /* read it */
+ if (fread(data, size, 1, ef->fp) != 1)
+ {
+ free(data);
+ data = NULL;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ /* compressed data */
+ else
+ {
+ void *tmp_data;
+
+ /* get size of data in file */
+ tmp_size = ef->header->directory->hash[hash].node[i].size;
+ tmp_data = malloc(tmp_size);
+ if (!tmp_data) break;
+ /* get size uncompressed */
+ size = ef->header->directory->hash[hash].node[i].data_size;
+ /* allocate data */
+ data = malloc(size);
+ if (data)
+ {
+ uLongf dlen;
+
+ /* if we already have the data in ram... copy that */
+ if (ef->header->directory->hash[hash].node[i].data)
+ memcpy(tmp_data,
+ ef->header->directory->hash[hash].node[i].data,
+ tmp_size);
+ /* or get data from disk */
+ else
+ {
+ /* seek to data location */
+ if (fseek(ef->fp, ef->header->directory->hash[hash].node[i].offset, SEEK_SET) < 0)
+ {
+ free(tmp_data);
+ free(data);
+ data = NULL;
+ break;
+ }
+ /* read it */
+ if (fread(tmp_data, tmp_size, 1, ef->fp) != 1)
+ {
+ free(tmp_data);
+ free(data);
+ data = NULL;
+ break;
+ }
+ }
+ /* decompress it */
+ dlen = size;
+ if (uncompress((Bytef *)data, &dlen,
+ tmp_data, (uLongf)tmp_size))
+ {
+ free(tmp_data);
+ free(data);
+ data = NULL;
+ break;
+ }
+ }
+ free(tmp_data);
+ break;
+ }
+ }
+ }
+ /* fill in return values */
+ *size_ret = size;
+ /* update access time */
+ return data;
+}
+
+int
+eet_write(Eet_File *ef, char *name, void *data, int size, int compress)
+{
+ int data_size;
+ int hash, node_size;
+ Eet_File_Node *node;
+ char *name2;
+ void *data2;
+
+ /* check to see its' an eet file pointer */
+ if ((!ef) || (ef->magic != EET_MAGIC_FILE)
+ || (!name) || (!data) || (size <= 0) ||
+ (ef->mode != EET_FILE_MODE_WRITE))
+ return 0;
+
+ if (!ef->header)
+ {
+ /* allocate header */
+ ef->header = calloc(sizeof(Eet_File_Header), 1);
+ if (!ef->header) return 0;
+ ef->header->magic = EET_MAGIC_FILE_HEADER;
+ /* allocate directory block in ram */
+ ef->header->directory = calloc(sizeof(Eet_File_Directory), 1);
+ if (!ef->header->directory) return 0;
+ /* 8 bit hash table (256 buckets) */
+ ef->header->directory->size = 8;
+ /* allocate base hash table */
+ ef->header->directory->hash = calloc(sizeof(Eet_File_Directory_Hash), (1 << (ef->header->directory->size - 1)));
+ if (!ef->header->directory->hash) return 0;
+ }
+ /* figure hash bucket */
+ hash = eet_hash_gen(name, ef->header->directory->size);
+ node_size = ef->header->directory->hash[hash].size;
+ /* dup name */
+ name2 = strdup(name);
+ if (!name2) return 0;
+ /* dup data */
+ data_size = size;
+ if (compress == 1)
+ data_size = 12 + ((size * 101) / 100);
+ data2 = malloc(data_size);
+ if (!data2)
+ {
+ free(name2);
+ return 0;
+ }
+ /* if we want to compress */
+ if (compress == 1)
+ {
+ uLongf buflen;
+
+ /* compress the data with max compression */
+ if (compress2((Bytef *)data2, &buflen, (Bytef *)data,
+ (uLong)size, 9) != Z_OK)
+ {
+ free(name2);
+ free(data2);
+ return 0;
+ }
+ /* record compressed chunk size */
+ data_size = (int)buflen;
+ if (data_size >= size)
+ {
+ compress = 0;
+ data_size = size;
+ }
+ }
+ if (!compress)
+ memcpy(data2, data, size);
+ /* increase hash bucket size */
+ node = realloc(ef->header->directory->hash[hash].node,
+ (node_size + 1) * sizeof(Eet_File_Node));
+ if (!node)
+ {
+ free(name2);
+ free(data2);
+ return 0;
+ }
+ /* resized node list set up */
+ ef->header->directory->hash[hash].node = node;
+ /* new node at end */
+ ef->header->directory->hash[hash].node[node_size].name = name2;
+ ef->header->directory->hash[hash].node[node_size].offset = 0;
+ ef->header->directory->hash[hash].node[node_size].compression = compress;
+ ef->header->directory->hash[hash].node[node_size].size = data_size;
+ ef->header->directory->hash[hash].node[node_size].data_size = size;
+ ef->header->directory->hash[hash].node[node_size].data = data2;
+ ef->header->directory->hash[hash].size++;
+
+ /* flags that writes are pending */
+ ef->writes_pending = 1;
+ /* update access time */
+ return size;
+}
+
+char **
+eet_list(Eet_File *ef, char *glob, int *count_ret)
+{
+ char **list_ret = NULL;
+ int list_count = 0;
+ int list_count_alloc = 0;
+ int i, j, num;
+
+ /* check to see its' an eet file pointer */
+ if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!glob))
+ {
+ if (count_ret) *count_ret = 0;
+ return NULL;
+ }
+ /* loop through all entries */
+ num = (1 << (ef->header->directory->size - 1));
+ for (i = 0; i < num; i++)
+ {
+ for (j = 0; j < ef->header->directory->hash[i].size; j++)
+ {
+ /* if the entry matches the input glob */
+ if (!fnmatch(glob, ef->header->directory->hash[i].node[j].name, 0))
+ {
+ char **new_list;
+
+ /* add it to our list */
+ list_count++;
+ /* only realloc in 32 entry chunks */
+ if (list_count > list_count_alloc)
+ {
+ list_count_alloc += 32;
+ 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] = ef->header->directory->hash[i].node[j].name;
+ }
+ }
+ }
+ /* return count and list */
+ if (count_ret) *count_ret = list_count;
+ return list_ret;
+}