move eet to HEAD
authorraster <raster>
Mon, 2 Dec 2002 23:39:26 +0000 (23:39 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Mon, 2 Dec 2002 23:39:26 +0000 (23:39 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/e17/libs/eet@6469 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

30 files changed:
.cvsignore [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
acconfig.h [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
configure.ac [new file with mode: 0644]
configure.in [new file with mode: 0644]
debian/.cvsignore [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/eet-config.1 [new file with mode: 0644]
debian/eet.1 [new file with mode: 0644]
debian/libeet0-dev.files [new file with mode: 0644]
debian/libeet0.files [new file with mode: 0644]
debian/rules [new file with mode: 0644]
eet-config.in [new file with mode: 0644]
eet.spec [new file with mode: 0644]
src/.cvsignore [new file with mode: 0644]
src/Makefile.am [new file with mode: 0644]
src/bin/.cvsignore [new file with mode: 0644]
src/bin/Makefile.am [new file with mode: 0644]
src/bin/eet_main.c [new file with mode: 0644]
src/lib/.cvsignore [new file with mode: 0644]
src/lib/Eet.h [new file with mode: 0644]
src/lib/Makefile.am [new file with mode: 0644]
src/lib/eet_data.c [new file with mode: 0644]
src/lib/eet_lib.c [new file with mode: 0644]

diff --git a/.cvsignore b/.cvsignore
new file mode 100644 (file)
index 0000000..2b9156e
--- /dev/null
@@ -0,0 +1,2 @@
+.config
+build-stamp
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..3a3ad7e
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,14 @@
+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.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..7e766de
--- /dev/null
@@ -0,0 +1,10 @@
+## 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
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/acconfig.h b/acconfig.h
new file mode 100644 (file)
index 0000000..bd2bb91
--- /dev/null
@@ -0,0 +1,3 @@
+#undef PACKAGE_SOURCE_DIR
+#undef PACKAGE_BIN_DIR
+#undef PACKAGE_LIB_DIR
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..9226176
--- /dev/null
@@ -0,0 +1,137 @@
+#!/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
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..a391da6
--- /dev/null
@@ -0,0 +1,75 @@
+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
+])
+
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..a391da6
--- /dev/null
@@ -0,0 +1,75 @@
+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
+])
+
diff --git a/debian/.cvsignore b/debian/.cvsignore
new file mode 100644 (file)
index 0000000..a0c9d09
--- /dev/null
@@ -0,0 +1,7 @@
+files
+libeet0
+libeet0-dev
+libeet0.postinst.debhelper
+libeet0.postrm.debhelper
+libeet0.substvars
+tmp
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..1201b20
--- /dev/null
@@ -0,0 +1,6 @@
+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
+
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..f8ea80e
--- /dev/null
@@ -0,0 +1,29 @@
+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.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..daf5283
--- /dev/null
@@ -0,0 +1,32 @@
+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.
diff --git a/debian/eet-config.1 b/debian/eet-config.1
new file mode 100644 (file)
index 0000000..b64bb22
--- /dev/null
@@ -0,0 +1,27 @@
+.\"                                      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).
diff --git a/debian/eet.1 b/debian/eet.1
new file mode 100644 (file)
index 0000000..f0f43f7
--- /dev/null
@@ -0,0 +1,61 @@
+.\"                                      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).
diff --git a/debian/libeet0-dev.files b/debian/libeet0-dev.files
new file mode 100644 (file)
index 0000000..606c89f
--- /dev/null
@@ -0,0 +1,4 @@
+usr/bin/eet-config
+usr/include/*
+usr/lib/lib*.a
+usr/lib/lib*.so
diff --git a/debian/libeet0.files b/debian/libeet0.files
new file mode 100644 (file)
index 0000000..31a86ab
--- /dev/null
@@ -0,0 +1,2 @@
+usr/bin/eet
+usr/lib/lib*.so.*
diff --git a/debian/rules b/debian/rules
new file mode 100644 (file)
index 0000000..171d5dc
--- /dev/null
@@ -0,0 +1,74 @@
+#!/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 
diff --git a/eet-config.in b/eet-config.in
new file mode 100644 (file)
index 0000000..d80b872
--- /dev/null
@@ -0,0 +1,59 @@
+#!/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
diff --git a/eet.spec b/eet.spec
new file mode 100644 (file)
index 0000000..419d95f
--- /dev/null
+++ b/eet.spec
@@ -0,0 +1,63 @@
+# 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
+
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644 (file)
index 0000000..2fa80b7
--- /dev/null
@@ -0,0 +1,3 @@
+eet
+eet-config
+libeet.so.0.0.0
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..7b45af6
--- /dev/null
@@ -0,0 +1,3 @@
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = lib bin
diff --git a/src/bin/.cvsignore b/src/bin/.cvsignore
new file mode 100644 (file)
index 0000000..2fa80b7
--- /dev/null
@@ -0,0 +1,3 @@
+eet
+eet-config
+libeet.so.0.0.0
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
new file mode 100644 (file)
index 0000000..49b8604
--- /dev/null
@@ -0,0 +1,12 @@
+## 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
diff --git a/src/bin/eet_main.c b/src/bin/eet_main.c
new file mode 100644 (file)
index 0000000..0bf1a71
--- /dev/null
@@ -0,0 +1,420 @@
+#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;
+}
diff --git a/src/lib/.cvsignore b/src/lib/.cvsignore
new file mode 100644 (file)
index 0000000..2fa80b7
--- /dev/null
@@ -0,0 +1,3 @@
+eet
+eet-config
+libeet.so.0.0.0
diff --git a/src/lib/Eet.h b/src/lib/Eet.h
new file mode 100644 (file)
index 0000000..57e231f
--- /dev/null
@@ -0,0 +1,268 @@
+#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
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
new file mode 100644 (file)
index 0000000..9477e00
--- /dev/null
@@ -0,0 +1,20 @@
+## 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
diff --git a/src/lib/eet_data.c b/src/lib/eet_data.c
new file mode 100644 (file)
index 0000000..d82b72b
--- /dev/null
@@ -0,0 +1,1765 @@
+#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;
+}
diff --git a/src/lib/eet_lib.c b/src/lib/eet_lib.c
new file mode 100644 (file)
index 0000000..e1cef9d
--- /dev/null
@@ -0,0 +1,889 @@
+#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;
+}