goat3d

changeset 14:188c697b3b49

- added a document describing the goat3d file format chunk hierarchy - started an alternative XML-based file format - added the openctm library
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 26 Sep 2013 04:47:05 +0300
parents 798df5111b56
children f1b4c27382ce
files .hgignore Makefile doc/goatfmt libs/openctm/LICENSE.txt libs/openctm/Makefile libs/openctm/README.txt libs/openctm/compressMG1.c libs/openctm/compressMG2.c libs/openctm/compressRAW.c libs/openctm/internal.h libs/openctm/liblzma/Alloc.c libs/openctm/liblzma/Alloc.h libs/openctm/liblzma/LzFind.c libs/openctm/liblzma/LzFind.h libs/openctm/liblzma/LzHash.h libs/openctm/liblzma/LzmaDec.c libs/openctm/liblzma/LzmaDec.h libs/openctm/liblzma/LzmaEnc.c libs/openctm/liblzma/LzmaEnc.h libs/openctm/liblzma/LzmaLib.c libs/openctm/liblzma/LzmaLib.h libs/openctm/liblzma/NameMangle.h libs/openctm/liblzma/Types.h libs/openctm/liblzma/readme.txt libs/openctm/openctm.c libs/openctm/openctm.h libs/openctm/openctmpp.h libs/openctm/stream.c src/chunk.h src/goat3d.cc src/goat3d_impl.h src/goat3d_scene.cc src/goat3d_write.cc src/goat3d_writexml.cc
diffstat 34 files changed, 11071 insertions(+), 433 deletions(-) [+]
line diff
     1.1 --- a/.hgignore	Tue Sep 10 15:29:45 2013 +0300
     1.2 +++ b/.hgignore	Thu Sep 26 04:47:05 2013 +0300
     1.3 @@ -9,3 +9,4 @@
     1.4  \.suo$
     1.5  x64/
     1.6  \.tlog$
     1.7 +^tags$
     2.1 --- a/Makefile	Tue Sep 10 15:29:45 2013 +0300
     2.2 +++ b/Makefile	Thu Sep 26 04:47:05 2013 +0300
     2.3 @@ -8,6 +8,11 @@
     2.4  obj = $(src:.cc=.o)
     2.5  dep = $(obj:.o=.d)
     2.6  
     2.7 +openctm = libs/openctm/libopenctm.a
     2.8 +
     2.9 +extinc = -Ilibs/openctm
    2.10 +extlibs = $(openctm)
    2.11 +
    2.12  name = goat3d
    2.13  so_major = 0
    2.14  so_minor = 1
    2.15 @@ -26,18 +31,21 @@
    2.16  	pic = -fPIC
    2.17  endif
    2.18  
    2.19 -CXXFLAGS = -pedantic -Wall $(dbg) $(opt) $(pic)
    2.20 -LDFLAGS = -lvmath -lanim
    2.21 +CXXFLAGS = -pedantic -Wall $(dbg) $(opt) $(pic) $(extinc)
    2.22 +LDFLAGS = $(extlibs) -lvmath -lanim
    2.23  
    2.24  .PHONY: all
    2.25  all: $(lib_so) $(lib_a)
    2.26  
    2.27 -$(lib_so): $(obj)
    2.28 +$(lib_so): $(obj) $(extlibs)
    2.29  	$(CXX) -o $@ $(shared) $(obj) $(LDFLAGS)
    2.30  
    2.31 -$(lib_a): $(obj)
    2.32 +$(lib_a): $(obj) $(extlibs)
    2.33  	$(AR) rcs $@ $(obj)
    2.34  
    2.35 +$(openctm):
    2.36 +	$(MAKE) -C libs/openctm
    2.37 +
    2.38  -include $(dep)
    2.39  
    2.40  %.d: %.cc
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/doc/goatfmt	Thu Sep 26 04:47:05 2013 +0300
     3.3 @@ -0,0 +1,110 @@
     3.4 +Chunk structure
     3.5 +---------------
     3.6 +
     3.7 +Leaf nodes which carry actual data are marked with <SINGLE_CHILD>, or
     3.8 +[MULTIPLE_CHILDREN]. Where choice is involved, options are seperated with the |
     3.9 +symbol.
    3.10 +
    3.11 +SCENE
    3.12 + +--ENV
    3.13 + |   +--AMBIENT
    3.14 + |   |   +--<FLOAT3>
    3.15 + |   +--FOG
    3.16 + |       +--FOG_COLOR
    3.17 + |       |   +--<FLOAT3>
    3.18 + |       +--FOG_EXP
    3.19 + |           +--<FLOAT>
    3.20 + +--MTL
    3.21 + |   +--MTL_NAME
    3.22 + |   |   +--<STRING>
    3.23 + |   +--MTL_ATTR
    3.24 + |       +--MTL_ATTR_NAME
    3.25 + |       |   +--<STRING>
    3.26 + |       +--MTL_ATTR_VAL
    3.27 + |       |   +--<FLOAT|FLOAT3|FLOAT4>
    3.28 + |       +--MTL_ATTR_MAP
    3.29 + |           +--<STRING>      (filename)
    3.30 + +--MESH
    3.31 + |   +--MESH_NAME
    3.32 + |   |   +--<STRING>
    3.33 + |   +--MESH_MATERIAL
    3.34 + |   |   +--<STRING>          (material name)
    3.35 + |   +--MESH_VERTEX_LIST
    3.36 + |   |   +--[FLOAT3]
    3.37 + |   +--MESH_NORMAL_LIST
    3.38 + |   |   +--[FLOAT3]
    3.39 + |   +--MESH_TANGENT_LIST
    3.40 + |   |   +--[FLOAT3]
    3.41 + |   +--MESH_TEXCOORD_LIST
    3.42 + |   |   +--[FLOAT3]
    3.43 + |   +--MESH_SKINWEIGHT_LIST
    3.44 + |   |   +--[FLOAT4]          (vector elements are the 4 skin weights/vertex)
    3.45 + |   +--MESH_SKINMATRIX_LIST
    3.46 + |   |   +--[INT4]            (vector elements are the 4 matrix indices/vertex)
    3.47 + |   +--MESH_COLOR_LIST
    3.48 + |   |   +--[FLOAT4]
    3.49 + |   +--MESH_BONES_LIST
    3.50 + |   |   +--[INT|STRING]      (list of bone nodes by name or index)
    3.51 + |   +--MESH_FACE_LIST
    3.52 + |   |   +--MESH_FACE
    3.53 + |   |       +--[INT]         (three INT chunks for the vertex indices)
    3.54 + |   +--MESH_FILE
    3.55 + |       +--<STRING>          (filename of mesh file to get all the data from)
    3.56 + +--LIGHT
    3.57 + |   +--LIGHT_NAME
    3.58 + |   |   +--<STRING>
    3.59 + |   +--LIGHT_POS
    3.60 + |   |   +--<FLOAT3>
    3.61 + |   +--LIGHT_COLOR
    3.62 + |   |   +--<FLOAT3>
    3.63 + |   +--LIGHT_ATTEN
    3.64 + |   |   +--<FLOAT3>           (constant, linear, and quadratic attenuation)
    3.65 + |   +--LIGHT_DISTANCE
    3.66 + |   |   +--<FLOAT>
    3.67 + |   +--LIGHT_DIR
    3.68 + |   |   +--<FLOAT3>
    3.69 + |   +--LIGHT_CONE_INNER
    3.70 + |   |   +--<FLOAT>
    3.71 + |   +--LIGHT_CONE_OUTER
    3.72 + |       +--<FLOAT>
    3.73 + +--CAMERA
    3.74 + |   +--CAMERA_NAME
    3.75 + |   |   +--<STRING>
    3.76 + |   +--CAMERA_POS
    3.77 + |   |   +--<FLOAT3>
    3.78 + |   +--CAMERA_TARGET
    3.79 + |   |   +--<FLOAT3>
    3.80 + |   +--CAMERA_FOV
    3.81 + |   |   +--<FLOAT>
    3.82 + |   +--CAMERA_NEARCLIP
    3.83 + |   |   +--<FLOAT>
    3.84 + |   +--CAMERA_FARCLIP
    3.85 + |       +--<FLOAT>
    3.86 + +--NODE
    3.87 +     +--NODE_NAME
    3.88 +     |   +--<STRING>
    3.89 +     +--NODE_PARENT
    3.90 +     |   +--<INT|STRING>
    3.91 +     +--NODE_MESH|NODE_LIGHT|NODE_CAMERA
    3.92 +     |   +--<INT|STRING>
    3.93 +     +--NODE_POS
    3.94 +     |   +--<FLOAT3>
    3.95 +     +--NODE_ROT
    3.96 +     |   +--<FLOAT4>           ([x, y, z], w <- real part)
    3.97 +     +--NODE_SCALE
    3.98 +     |   +--<FLOAT3>
    3.99 +     +--NODE_PIVOT
   3.100 +     |   +--<FLOAT3>
   3.101 +     +--NODE_MATRIX0
   3.102 +     |   +--<FLOAT4>           (first row)
   3.103 +     +--NODE_MATRIX1
   3.104 +     |   +--<FLOAT4>           (second row)
   3.105 +     +--NODE_MATRIX2
   3.106 +         +--<FLOAT4>           (third row)
   3.107 +
   3.108 +NOTES:
   3.109 + * Name chunks are mandatory. If something doesn't have a name, one must be made
   3.110 +   up, even if it's just "object%d".
   3.111 + * In node chunks, both POS/ROT/SCALE, and MATRIX0/MATRIX1/MATRIX2 are mandatory
   3.112 +   and they must agree. Makes it easy for the reader to pick the transformation
   3.113 +   data in whichever way is more convenient.
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/libs/openctm/LICENSE.txt	Thu Sep 26 04:47:05 2013 +0300
     4.3 @@ -0,0 +1,20 @@
     4.4 +Copyright (c) 2009-2010 Marcus Geelnard
     4.5 +
     4.6 +This software is provided 'as-is', without any express or implied
     4.7 +warranty. In no event will the authors be held liable for any damages
     4.8 +arising from the use of this software.
     4.9 +
    4.10 +Permission is granted to anyone to use this software for any purpose,
    4.11 +including commercial applications, and to alter it and redistribute it
    4.12 +freely, subject to the following restrictions:
    4.13 +
    4.14 +    1. The origin of this software must not be misrepresented; you must not
    4.15 +    claim that you wrote the original software. If you use this software
    4.16 +    in a product, an acknowledgment in the product documentation would be
    4.17 +    appreciated but is not required.
    4.18 +
    4.19 +    2. Altered source versions must be plainly marked as such, and must not
    4.20 +    be misrepresented as being the original software.
    4.21 +
    4.22 +    3. This notice may not be removed or altered from any source
    4.23 +    distribution.
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/libs/openctm/Makefile	Thu Sep 26 04:47:05 2013 +0300
     5.3 @@ -0,0 +1,16 @@
     5.4 +src = $(wildcard *.c) $(wildcard liblzma/*.c)
     5.5 +obj = $(src:.c=.o)
     5.6 +lib = libopenctm.a
     5.7 +
     5.8 +ifneq ($(shell uname -s), Darwin)
     5.9 +	pic = -fPIC
    5.10 +endif
    5.11 +
    5.12 +CFLAGS = -g -Iliblzma $(pic)
    5.13 +
    5.14 +$(lib): $(obj)
    5.15 +	$(AR) rcs $@ $(obj)
    5.16 +
    5.17 +.PHONY: clean
    5.18 +clean:
    5.19 +	rm -f $(obj) $(lib)
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/libs/openctm/README.txt	Thu Sep 26 04:47:05 2013 +0300
     6.3 @@ -0,0 +1,152 @@
     6.4 +1. INTRODUCTION
     6.5 +===============
     6.6 +
     6.7 +Welcome to OpenCTM!
     6.8 +
     6.9 +OpenCTM is a file format, a software library and a tool set for compression of
    6.10 +3D triangle meshes. The geometry is compressed to a fraction of comparable file
    6.11 +formats (3DS, STL, COLLADA, VRML...), and the format is easily accessible
    6.12 +through a simple, portable API.
    6.13 +
    6.14 +The library is written in portable C (C99), and should compile nicely on any
    6.15 +32/64-bit system regardless of endianity (big endian or little endian).
    6.16 +
    6.17 +
    6.18 +2. LICENSE
    6.19 +==========
    6.20 +
    6.21 +The OpenCTM API and the OpenCTM tools are released under the zlib/libpng
    6.22 +license (see LICENSE.txt).
    6.23 +
    6.24 +3. CREDITS
    6.25 +==========
    6.26 +
    6.27 +Many people have helped out in the development process of OpenCTM, with
    6.28 +valuable feedback, programming efforts, test models and conceptual ideas.
    6.29 +Also, OpenCTM relies heavily on many other open source projects.
    6.30 +
    6.31 +Here is an incomplete list of persons that deserve credit:
    6.32 +
    6.33 +- Igor Pavlov (LZMA library)
    6.34 +- Jonas Innala (COLLADA importer, Maya exporter plugin)
    6.35 +- Ilian Dinev (help with the OpenCTM file format design and the LWO loader)
    6.36 +- Lee Thomason (TinyXML)
    6.37 +- Diego Nehab (RPly - for loading PLY files)
    6.38 +- Lev Povalahev, Marcelo E. Magallon, Milan Ikits (GLEW)
    6.39 +- Thomas G. Lane, Guido Vollbeding (libjpeg)
    6.40 +- Jean-loup Gailly, Mark Adler (zlib)
    6.41 +- Daniel Karling (pnglite)
    6.42 +
    6.43 +During the development of OpenCTM, the following software has been used
    6.44 +extensively:
    6.45 +
    6.46 +- Ubuntu (www.ubuntu.com)
    6.47 +- Blender (www.blender.org)
    6.48 +- GCC (gcc.gnu.org)
    6.49 +- SciTE (www.scintilla.org/SciTE.html)
    6.50 +- Notepad++ (notepad-plus.sourceforge.net)
    6.51 +- Smultron (smultron.sourceforge.net)
    6.52 +
    6.53 +Legal notices:
    6.54 +
    6.55 +- This software is based in part on the work of the Independent JPEG Group.
    6.56 +
    6.57 +
    6.58 +4. CHANGES
    6.59 +==========
    6.60 +
    6.61 +v1.0.3 - 2010.01.15
    6.62 +-------------------
    6.63 +- Added support for PNG format textures (ctmviewer).
    6.64 +
    6.65 +- Added support for LightWave LWO files (ctmconv and ctmviewer).
    6.66 +
    6.67 +- Added support for Geomview OFF files, e.g. as used by the Princeton Shape
    6.68 +  Benchmark (ctmconv and ctmviewer).
    6.69 +
    6.70 +- Improved the OBJ file loader (ctmviewer and ctmconv).
    6.71 +
    6.72 +- Experimental support for VRML 2.0 files - export only (ctmconv and ctmviewer).
    6.73 +
    6.74 +- Made it possible to run ctmviewer without command line arguments.
    6.75 +
    6.76 +- Improved the normal calculation algorithm (ctmviewer and ctmconv).
    6.77 +
    6.78 +- Normals are no longer exported if no normals were present in the input file
    6.79 +  (ctmviewer).
    6.80 +
    6.81 +
    6.82 +v1.0.2 - 2009.12.13
    6.83 +-------------------
    6.84 +- Added an OpenCTM exporter plugin for Maya [Jonas Innala].
    6.85 +
    6.86 +- Added the possiblity to save and load files from ctmviewer, effectively
    6.87 +  turning it into a quick and simple converter tool (without all the options
    6.88 +  in the ctmconv program, though).
    6.89 +
    6.90 +- Added a function to load texture files from ctmviewer.
    6.91 +
    6.92 +- Improved the camera control in ctmviewer (panning with the right mouse
    6.93 +  button, zooming with the middle mouse button and the mouse wheel, feature
    6.94 +  focusing by double clicking, Y/Z up axis selection and "fit to screen"
    6.95 +  function).
    6.96 +
    6.97 +- Added a GUI dialog for showing errors in ctmviewer (this is especially useful
    6.98 +  under Windows, where console output is disabeled).
    6.99 +
   6.100 +- Added an option for calculating the normals in ctmconv (if the input file
   6.101 +  does not have normals).
   6.102 +
   6.103 +- Added options for turning off normals, texture coordinates and/or vertex
   6.104 +  colors for the output file in ctmconv.
   6.105 +
   6.106 +- Added manuals for ctmviewer and ctmconv (man pages).
   6.107 +
   6.108 +- Added a "make install" build target for Mac OS X and Linux for simple system
   6.109 +  wide installation (see COMPILING.txt).
   6.110 +
   6.111 +- NOTE: The Linux/X11 version of ctmviewer now reqires GTK+ 2.0.
   6.112 +
   6.113 +
   6.114 +v1.0.1 - 2009.11.15
   6.115 +-------------------
   6.116 +- Notable reduction of the memory footprint by tuning of the LZMA compression
   6.117 +  parameters.
   6.118 +
   6.119 +- Added a Wavefront OBJ file importer/exporter.
   6.120 +
   6.121 +- Some improvements to ctmviewer and ctmconv.
   6.122 +
   6.123 +- Some directory structure and build system cleanups.
   6.124 +
   6.125 +
   6.126 +v1.0 - 2009.11.09
   6.127 +-----------------
   6.128 +- Added a COLLADA converter module to the ctmconv program [Jonas Innala].
   6.129 +
   6.130 +- Added Python bindings and a demo Python program.
   6.131 +
   6.132 +- Improved the internal mesh integrity checking, to minimize the risk of invalid
   6.133 +  data processing.
   6.134 +
   6.135 +- Improved the file format specification document.
   6.136 +
   6.137 +
   6.138 +v0.8 (beta) - 2009.09.14
   6.139 +------------------------
   6.140 +- Introduced a new API function for controlling the compression level
   6.141 +  (ctmCompressionLevel), and set the default compression level to 5 (rather
   6.142 +  than 9, which would eat a lot of memory, usally without much difference).
   6.143 +
   6.144 +- Changed the name "texture map" in the API to "UV map" (and all
   6.145 +  corresponding constant and function names). This is more in line with
   6.146 +  the nomenclature of most 3D authoring software, and avoids the confusion
   6.147 +  with the term texture mapping in 3D hardware (which is not limited to
   6.148 +  2D UV mapping coordinates).
   6.149 +
   6.150 +- A few updates to the documentation.
   6.151 +
   6.152 +
   6.153 +v0.7 (beta) - 2009.08.29
   6.154 +------------------------
   6.155 +- This was the first public release of OpenCTM.
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/libs/openctm/compressMG1.c	Thu Sep 26 04:47:05 2013 +0300
     7.3 @@ -0,0 +1,324 @@
     7.4 +//-----------------------------------------------------------------------------
     7.5 +// Product:     OpenCTM
     7.6 +// File:        compressMG1.c
     7.7 +// Description: Implementation of the MG1 compression method.
     7.8 +//-----------------------------------------------------------------------------
     7.9 +// Copyright (c) 2009-2010 Marcus Geelnard
    7.10 +//
    7.11 +// This software is provided 'as-is', without any express or implied
    7.12 +// warranty. In no event will the authors be held liable for any damages
    7.13 +// arising from the use of this software.
    7.14 +//
    7.15 +// Permission is granted to anyone to use this software for any purpose,
    7.16 +// including commercial applications, and to alter it and redistribute it
    7.17 +// freely, subject to the following restrictions:
    7.18 +//
    7.19 +//     1. The origin of this software must not be misrepresented; you must not
    7.20 +//     claim that you wrote the original software. If you use this software
    7.21 +//     in a product, an acknowledgment in the product documentation would be
    7.22 +//     appreciated but is not required.
    7.23 +//
    7.24 +//     2. Altered source versions must be plainly marked as such, and must not
    7.25 +//     be misrepresented as being the original software.
    7.26 +//
    7.27 +//     3. This notice may not be removed or altered from any source
    7.28 +//     distribution.
    7.29 +//-----------------------------------------------------------------------------
    7.30 +
    7.31 +#include <stdlib.h>
    7.32 +#include <math.h>
    7.33 +#include "openctm.h"
    7.34 +#include "internal.h"
    7.35 +
    7.36 +#ifdef __DEBUG_
    7.37 +#include <stdio.h>
    7.38 +#endif
    7.39 +
    7.40 +
    7.41 +//-----------------------------------------------------------------------------
    7.42 +// _compareTriangle() - Comparator for the triangle sorting.
    7.43 +//-----------------------------------------------------------------------------
    7.44 +static int _compareTriangle(const void * elem1, const void * elem2)
    7.45 +{
    7.46 +  CTMuint * tri1 = (CTMuint *) elem1;
    7.47 +  CTMuint * tri2 = (CTMuint *) elem2;
    7.48 +  if(tri1[0] != tri2[0])
    7.49 +    return tri1[0] - tri2[0];
    7.50 +  else
    7.51 +    return tri1[1] - tri2[1];
    7.52 +}
    7.53 +
    7.54 +//-----------------------------------------------------------------------------
    7.55 +// _ctmReArrangeTriangles() - Re-arrange all triangles for optimal
    7.56 +// compression.
    7.57 +//-----------------------------------------------------------------------------
    7.58 +static void _ctmReArrangeTriangles(_CTMcontext * self, CTMuint * aIndices)
    7.59 +{
    7.60 +  CTMuint * tri, tmp, i;
    7.61 +
    7.62 +  // Step 1: Make sure that the first index of each triangle is the smallest
    7.63 +  // one (rotate triangle nodes if necessary)
    7.64 +  for(i = 0; i < self->mTriangleCount; ++ i)
    7.65 +  {
    7.66 +    tri = &aIndices[i * 3];
    7.67 +    if((tri[1] < tri[0]) && (tri[1] < tri[2]))
    7.68 +    {
    7.69 +      tmp = tri[0];
    7.70 +      tri[0] = tri[1];
    7.71 +      tri[1] = tri[2];
    7.72 +      tri[2] = tmp;
    7.73 +    }
    7.74 +    else if((tri[2] < tri[0]) && (tri[2] < tri[1]))
    7.75 +    {
    7.76 +      tmp = tri[0];
    7.77 +      tri[0] = tri[2];
    7.78 +      tri[2] = tri[1];
    7.79 +      tri[1] = tmp;
    7.80 +    }
    7.81 +  }
    7.82 +
    7.83 +  // Step 2: Sort the triangles based on the first triangle index
    7.84 +  qsort((void *) aIndices, self->mTriangleCount, sizeof(CTMuint) * 3, _compareTriangle);
    7.85 +}
    7.86 +
    7.87 +//-----------------------------------------------------------------------------
    7.88 +// _ctmMakeIndexDeltas() - Calculate various forms of derivatives in order to
    7.89 +// reduce data entropy.
    7.90 +//-----------------------------------------------------------------------------
    7.91 +static void _ctmMakeIndexDeltas(_CTMcontext * self, CTMuint * aIndices)
    7.92 +{
    7.93 +  CTMint i;
    7.94 +  for(i = self->mTriangleCount - 1; i >= 0; -- i)
    7.95 +  {
    7.96 +    // Step 1: Calculate delta from second triangle index to the previous
    7.97 +    // second triangle index, if the previous triangle shares the same first
    7.98 +    // index, otherwise calculate the delta to the first triangle index
    7.99 +    if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3]))
   7.100 +      aIndices[i * 3 + 1] -= aIndices[(i - 1) * 3 + 1];
   7.101 +    else
   7.102 +      aIndices[i * 3 + 1] -= aIndices[i * 3];
   7.103 +
   7.104 +    // Step 2: Calculate delta from third triangle index to the first triangle
   7.105 +    // index
   7.106 +    aIndices[i * 3 + 2] -= aIndices[i * 3];
   7.107 +
   7.108 +    // Step 3: Calculate derivative of the first triangle index
   7.109 +    if(i >= 1)
   7.110 +      aIndices[i * 3] -= aIndices[(i - 1) * 3];
   7.111 +  }
   7.112 +}
   7.113 +
   7.114 +//-----------------------------------------------------------------------------
   7.115 +// _ctmRestoreIndices() - Restore original indices (inverse derivative
   7.116 +// operation).
   7.117 +//-----------------------------------------------------------------------------
   7.118 +static void _ctmRestoreIndices(_CTMcontext * self, CTMuint * aIndices)
   7.119 +{
   7.120 +  CTMuint i;
   7.121 +
   7.122 +  for(i = 0; i < self->mTriangleCount; ++ i)
   7.123 +  {
   7.124 +    // Step 1: Reverse derivative of the first triangle index
   7.125 +    if(i >= 1)
   7.126 +      aIndices[i * 3] += aIndices[(i - 1) * 3];
   7.127 +
   7.128 +    // Step 2: Reverse delta from third triangle index to the first triangle
   7.129 +    // index
   7.130 +    aIndices[i * 3 + 2] += aIndices[i * 3];
   7.131 +
   7.132 +    // Step 3: Reverse delta from second triangle index to the previous
   7.133 +    // second triangle index, if the previous triangle shares the same first
   7.134 +    // index, otherwise reverse the delta to the first triangle index
   7.135 +    if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3]))
   7.136 +      aIndices[i * 3 + 1] += aIndices[(i - 1) * 3 + 1];
   7.137 +    else
   7.138 +      aIndices[i * 3 + 1] += aIndices[i * 3];
   7.139 +  }
   7.140 +}
   7.141 +
   7.142 +//-----------------------------------------------------------------------------
   7.143 +// _ctmCompressMesh_MG1() - Compress the mesh that is stored in the CTM
   7.144 +// context, and write it the the output stream in the CTM context.
   7.145 +//-----------------------------------------------------------------------------
   7.146 +int _ctmCompressMesh_MG1(_CTMcontext * self)
   7.147 +{
   7.148 +  CTMuint * indices;
   7.149 +  _CTMfloatmap * map;
   7.150 +  CTMuint i;
   7.151 +
   7.152 +#ifdef __DEBUG_
   7.153 +  printf("COMPRESSION METHOD: MG1\n");
   7.154 +#endif
   7.155 +
   7.156 +  // Perpare (sort) indices
   7.157 +  indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3);
   7.158 +  if(!indices)
   7.159 +  {
   7.160 +    self->mError = CTM_OUT_OF_MEMORY;
   7.161 +    return CTM_FALSE;
   7.162 +  }
   7.163 +  for(i = 0; i < self->mTriangleCount * 3; ++ i)
   7.164 +    indices[i] = self->mIndices[i];
   7.165 +  _ctmReArrangeTriangles(self, indices);
   7.166 +
   7.167 +  // Calculate index deltas (entropy-reduction)
   7.168 +  _ctmMakeIndexDeltas(self, indices);
   7.169 +
   7.170 +  // Write triangle indices
   7.171 +#ifdef __DEBUG_
   7.172 +  printf("Inidices: ");
   7.173 +#endif
   7.174 +  _ctmStreamWrite(self, (void *) "INDX", 4);
   7.175 +  if(!_ctmStreamWritePackedInts(self, (CTMint *) indices, self->mTriangleCount, 3, CTM_FALSE))
   7.176 +  {
   7.177 +    free((void *) indices);
   7.178 +    return CTM_FALSE;
   7.179 +  }
   7.180 +
   7.181 +  // Free temporary resources
   7.182 +  free((void *) indices);
   7.183 +
   7.184 +  // Write vertices
   7.185 +#ifdef __DEBUG_
   7.186 +  printf("Vertices: ");
   7.187 +#endif
   7.188 +  _ctmStreamWrite(self, (void *) "VERT", 4);
   7.189 +  if(!_ctmStreamWritePackedFloats(self, self->mVertices, self->mVertexCount * 3, 1))
   7.190 +  {
   7.191 +    free((void *) indices);
   7.192 +    return CTM_FALSE;
   7.193 +  }
   7.194 +
   7.195 +  // Write normals
   7.196 +  if(self->mNormals)
   7.197 +  {
   7.198 +#ifdef __DEBUG_
   7.199 +    printf("Normals: ");
   7.200 +#endif
   7.201 +    _ctmStreamWrite(self, (void *) "NORM", 4);
   7.202 +    if(!_ctmStreamWritePackedFloats(self, self->mNormals, self->mVertexCount, 3))
   7.203 +      return CTM_FALSE;
   7.204 +  }
   7.205 +
   7.206 +  // Write UV maps
   7.207 +  map = self->mUVMaps;
   7.208 +  while(map)
   7.209 +  {
   7.210 +#ifdef __DEBUG_
   7.211 +    printf("UV coordinates (%s): ", map->mName ? map->mName : "no name");
   7.212 +#endif
   7.213 +    _ctmStreamWrite(self, (void *) "TEXC", 4);
   7.214 +    _ctmStreamWriteSTRING(self, map->mName);
   7.215 +    _ctmStreamWriteSTRING(self, map->mFileName);
   7.216 +    if(!_ctmStreamWritePackedFloats(self, map->mValues, self->mVertexCount, 2))
   7.217 +      return CTM_FALSE;
   7.218 +    map = map->mNext;
   7.219 +  }
   7.220 +
   7.221 +  // Write attribute maps
   7.222 +  map = self->mAttribMaps;
   7.223 +  while(map)
   7.224 +  {
   7.225 +#ifdef __DEBUG_
   7.226 +    printf("Vertex attributes (%s): ", map->mName ? map->mName : "no name");
   7.227 +#endif
   7.228 +    _ctmStreamWrite(self, (void *) "ATTR", 4);
   7.229 +    _ctmStreamWriteSTRING(self, map->mName);
   7.230 +    if(!_ctmStreamWritePackedFloats(self, map->mValues, self->mVertexCount, 4))
   7.231 +      return CTM_FALSE;
   7.232 +    map = map->mNext;
   7.233 +  }
   7.234 +
   7.235 +  return CTM_TRUE;
   7.236 +}
   7.237 +
   7.238 +//-----------------------------------------------------------------------------
   7.239 +// _ctmUncompressMesh_MG1() - Uncmpress the mesh from the input stream in the
   7.240 +// CTM context, and store the resulting mesh in the CTM context.
   7.241 +//-----------------------------------------------------------------------------
   7.242 +int _ctmUncompressMesh_MG1(_CTMcontext * self)
   7.243 +{
   7.244 +  CTMuint * indices;
   7.245 +  _CTMfloatmap * map;
   7.246 +  CTMuint i;
   7.247 +
   7.248 +  // Allocate memory for the indices
   7.249 +  indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3);
   7.250 +  if(!indices)
   7.251 +  {
   7.252 +    self->mError = CTM_OUT_OF_MEMORY;
   7.253 +    return CTM_FALSE;
   7.254 +  }
   7.255 +
   7.256 +  // Read triangle indices
   7.257 +  if(_ctmStreamReadUINT(self) != FOURCC("INDX"))
   7.258 +  {
   7.259 +    self->mError = CTM_BAD_FORMAT;
   7.260 +    free(indices);
   7.261 +    return CTM_FALSE;
   7.262 +  }
   7.263 +  if(!_ctmStreamReadPackedInts(self, (CTMint *) indices, self->mTriangleCount, 3, CTM_FALSE))
   7.264 +    return CTM_FALSE;
   7.265 +
   7.266 +  // Restore indices
   7.267 +  _ctmRestoreIndices(self, indices);
   7.268 +  for(i = 0; i < self->mTriangleCount * 3; ++ i)
   7.269 +    self->mIndices[i] = indices[i];
   7.270 +
   7.271 +  // Free temporary resources
   7.272 +  free(indices);
   7.273 +
   7.274 +  // Read vertices
   7.275 +  if(_ctmStreamReadUINT(self) != FOURCC("VERT"))
   7.276 +  {
   7.277 +    self->mError = CTM_BAD_FORMAT;
   7.278 +    return CTM_FALSE;
   7.279 +  }
   7.280 +  if(!_ctmStreamReadPackedFloats(self, self->mVertices, self->mVertexCount * 3, 1))
   7.281 +    return CTM_FALSE;
   7.282 +
   7.283 +  // Read normals
   7.284 +  if(self->mNormals)
   7.285 +  {
   7.286 +    if(_ctmStreamReadUINT(self) != FOURCC("NORM"))
   7.287 +    {
   7.288 +      self->mError = CTM_BAD_FORMAT;
   7.289 +      return CTM_FALSE;
   7.290 +    }
   7.291 +    if(!_ctmStreamReadPackedFloats(self, self->mNormals, self->mVertexCount, 3))
   7.292 +      return CTM_FALSE;
   7.293 +  }
   7.294 +
   7.295 +  // Read UV maps
   7.296 +  map = self->mUVMaps;
   7.297 +  while(map)
   7.298 +  {
   7.299 +    if(_ctmStreamReadUINT(self) != FOURCC("TEXC"))
   7.300 +    {
   7.301 +      self->mError = CTM_BAD_FORMAT;
   7.302 +      return 0;
   7.303 +    }
   7.304 +    _ctmStreamReadSTRING(self, &map->mName);
   7.305 +    _ctmStreamReadSTRING(self, &map->mFileName);
   7.306 +    if(!_ctmStreamReadPackedFloats(self, map->mValues, self->mVertexCount, 2))
   7.307 +      return CTM_FALSE;
   7.308 +    map = map->mNext;
   7.309 +  }
   7.310 +
   7.311 +  // Read vertex attribute maps
   7.312 +  map = self->mAttribMaps;
   7.313 +  while(map)
   7.314 +  {
   7.315 +    if(_ctmStreamReadUINT(self) != FOURCC("ATTR"))
   7.316 +    {
   7.317 +      self->mError = CTM_BAD_FORMAT;
   7.318 +      return 0;
   7.319 +    }
   7.320 +    _ctmStreamReadSTRING(self, &map->mName);
   7.321 +    if(!_ctmStreamReadPackedFloats(self, map->mValues, self->mVertexCount, 4))
   7.322 +      return CTM_FALSE;
   7.323 +    map = map->mNext;
   7.324 +  }
   7.325 +
   7.326 +  return CTM_TRUE;
   7.327 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/libs/openctm/compressMG2.c	Thu Sep 26 04:47:05 2013 +0300
     8.3 @@ -0,0 +1,1319 @@
     8.4 +//-----------------------------------------------------------------------------
     8.5 +// Product:     OpenCTM
     8.6 +// File:        compressMG2.c
     8.7 +// Description: Implementation of the MG2 compression method.
     8.8 +//-----------------------------------------------------------------------------
     8.9 +// Copyright (c) 2009-2010 Marcus Geelnard
    8.10 +//
    8.11 +// This software is provided 'as-is', without any express or implied
    8.12 +// warranty. In no event will the authors be held liable for any damages
    8.13 +// arising from the use of this software.
    8.14 +//
    8.15 +// Permission is granted to anyone to use this software for any purpose,
    8.16 +// including commercial applications, and to alter it and redistribute it
    8.17 +// freely, subject to the following restrictions:
    8.18 +//
    8.19 +//     1. The origin of this software must not be misrepresented; you must not
    8.20 +//     claim that you wrote the original software. If you use this software
    8.21 +//     in a product, an acknowledgment in the product documentation would be
    8.22 +//     appreciated but is not required.
    8.23 +//
    8.24 +//     2. Altered source versions must be plainly marked as such, and must not
    8.25 +//     be misrepresented as being the original software.
    8.26 +//
    8.27 +//     3. This notice may not be removed or altered from any source
    8.28 +//     distribution.
    8.29 +//-----------------------------------------------------------------------------
    8.30 +
    8.31 +#include <stdlib.h>
    8.32 +#include <math.h>
    8.33 +#include "openctm.h"
    8.34 +#include "internal.h"
    8.35 +
    8.36 +#ifdef __DEBUG_
    8.37 +#include <stdio.h>
    8.38 +#endif
    8.39 +
    8.40 +// We need PI
    8.41 +#ifndef PI
    8.42 +#define PI 3.141592653589793238462643f
    8.43 +#endif
    8.44 +
    8.45 +
    8.46 +//-----------------------------------------------------------------------------
    8.47 +// _CTMgrid - 3D space subdivision grid.
    8.48 +//-----------------------------------------------------------------------------
    8.49 +typedef struct {
    8.50 +  // Axis-aligned boudning box for the grid.
    8.51 +  CTMfloat mMin[3];
    8.52 +  CTMfloat mMax[3];
    8.53 +
    8.54 +  // How many divisions per axis (minimum 1).
    8.55 +  CTMuint mDivision[3];
    8.56 +
    8.57 +  // Size of each grid box.
    8.58 +  CTMfloat mSize[3];
    8.59 +} _CTMgrid;
    8.60 +
    8.61 +//-----------------------------------------------------------------------------
    8.62 +// _CTMsortvertex - Vertex information.
    8.63 +//-----------------------------------------------------------------------------
    8.64 +typedef struct {
    8.65 +  // Vertex X coordinate (used for sorting).
    8.66 +  CTMfloat x;
    8.67 +
    8.68 +  // Grid index. This is the index into the 3D space subdivision grid.
    8.69 +  CTMuint mGridIndex;
    8.70 +
    8.71 +  // Original index (before sorting).
    8.72 +  CTMuint mOriginalIndex;
    8.73 +} _CTMsortvertex;
    8.74 +
    8.75 +//-----------------------------------------------------------------------------
    8.76 +// _ctmSetupGrid() - Setup the 3D space subdivision grid.
    8.77 +//-----------------------------------------------------------------------------
    8.78 +static void _ctmSetupGrid(_CTMcontext * self, _CTMgrid * aGrid)
    8.79 +{
    8.80 +  CTMuint i;
    8.81 +  CTMfloat factor[3], sum, wantedGrids;
    8.82 +
    8.83 +  // Calculate the mesh bounding box
    8.84 +  aGrid->mMin[0] = aGrid->mMax[0] = self->mVertices[0];
    8.85 +  aGrid->mMin[1] = aGrid->mMax[1] = self->mVertices[1];
    8.86 +  aGrid->mMin[2] = aGrid->mMax[2] = self->mVertices[2];
    8.87 +  for(i = 1; i < self->mVertexCount; ++ i)
    8.88 +  {
    8.89 +    if(self->mVertices[i * 3] < aGrid->mMin[0])
    8.90 +      aGrid->mMin[0] = self->mVertices[i * 3];
    8.91 +    else if(self->mVertices[i * 3] > aGrid->mMax[0])
    8.92 +      aGrid->mMax[0] = self->mVertices[i * 3];
    8.93 +    if(self->mVertices[i * 3 + 1] < aGrid->mMin[1])
    8.94 +      aGrid->mMin[1] = self->mVertices[i * 3 + 1];
    8.95 +    else if(self->mVertices[i * 3 + 1] > aGrid->mMax[1])
    8.96 +      aGrid->mMax[1] = self->mVertices[i * 3 + 1];
    8.97 +    if(self->mVertices[i * 3 + 2] < aGrid->mMin[2])
    8.98 +      aGrid->mMin[2] = self->mVertices[i * 3 + 2];
    8.99 +    else if(self->mVertices[i * 3 + 2] > aGrid->mMax[2])
   8.100 +      aGrid->mMax[2] = self->mVertices[i * 3 + 2];
   8.101 +  }
   8.102 +
   8.103 +  // Determine optimal grid resolution, based on the number of vertices and
   8.104 +  // the bounding box.
   8.105 +  // NOTE: This algorithm is quite crude, and could very well be optimized for
   8.106 +  // better compression levels in the future without affecting the file format
   8.107 +  // or backward compatibility at all.
   8.108 +  for(i = 0; i < 3; ++ i)
   8.109 +    factor[i] = aGrid->mMax[i] - aGrid->mMin[i];
   8.110 +  sum = factor[0] + factor[1] + factor[2];
   8.111 +  if(sum > 1e-30f)
   8.112 +  {
   8.113 +    sum = 1.0f / sum;
   8.114 +    for(i = 0; i < 3; ++ i)
   8.115 +      factor[i] *= sum;
   8.116 +    wantedGrids = powf(100.0f * self->mVertexCount, 1.0f / 3.0f);
   8.117 +    for(i = 0; i < 3; ++ i)
   8.118 +    {
   8.119 +      aGrid->mDivision[i] = (CTMuint) ceilf(wantedGrids * factor[i]);
   8.120 +      if(aGrid->mDivision[i] < 1)
   8.121 +        aGrid->mDivision[i] = 1;
   8.122 +    }
   8.123 +  }
   8.124 +  else
   8.125 +  {
   8.126 +    aGrid->mDivision[0] = 4;
   8.127 +    aGrid->mDivision[1] = 4;
   8.128 +    aGrid->mDivision[2] = 4;
   8.129 +  }
   8.130 +#ifdef __DEBUG_
   8.131 +  printf("Division: (%d %d %d)\n", aGrid->mDivision[0], aGrid->mDivision[1], aGrid->mDivision[2]);
   8.132 +#endif
   8.133 +
   8.134 +  // Calculate grid sizes
   8.135 +  for(i = 0; i < 3; ++ i)
   8.136 +    aGrid->mSize[i] = (aGrid->mMax[i] - aGrid->mMin[i]) / aGrid->mDivision[i];
   8.137 +}
   8.138 +
   8.139 +//-----------------------------------------------------------------------------
   8.140 +// _ctmPointToGridIdx() - Convert a point to a grid index.
   8.141 +//-----------------------------------------------------------------------------
   8.142 +static CTMuint _ctmPointToGridIdx(_CTMgrid * aGrid, CTMfloat * aPoint)
   8.143 +{
   8.144 +  CTMuint i, idx[3];
   8.145 +
   8.146 +  for(i = 0; i < 3; ++ i)
   8.147 +  {
   8.148 +    idx[i] = (CTMuint) floorf((aPoint[i] - aGrid->mMin[i]) / aGrid->mSize[i]);
   8.149 +    if(idx[i] >= aGrid->mDivision[i])
   8.150 +      idx[i] = aGrid->mDivision[i] - 1;
   8.151 +  }
   8.152 +
   8.153 +  return idx[0] + aGrid->mDivision[0] * (idx[1] + aGrid->mDivision[1] * idx[2]);
   8.154 +}
   8.155 +
   8.156 +//-----------------------------------------------------------------------------
   8.157 +// _ctmGridIdxToPoint() - Convert a grid index to a point (the min x/y/z for
   8.158 +// the given grid box).
   8.159 +//-----------------------------------------------------------------------------
   8.160 +static void _ctmGridIdxToPoint(_CTMgrid * aGrid, CTMuint aIdx, CTMfloat * aPoint)
   8.161 +{
   8.162 +  CTMuint gridIdx[3], zdiv, ydiv, i;
   8.163 +
   8.164 +  zdiv = aGrid->mDivision[0] * aGrid->mDivision[1];
   8.165 +  ydiv = aGrid->mDivision[0];
   8.166 +
   8.167 +  gridIdx[2] =  aIdx / zdiv;
   8.168 +  aIdx -= gridIdx[2] * zdiv;
   8.169 +  gridIdx[1] =  aIdx / ydiv;
   8.170 +  aIdx -= gridIdx[1] * ydiv;
   8.171 +  gridIdx[0] = aIdx;
   8.172 +
   8.173 +  for(i = 0; i < 3; ++ i)
   8.174 +    aPoint[i] = gridIdx[i] * aGrid->mSize[i] + aGrid->mMin[i];
   8.175 +}
   8.176 +
   8.177 +//-----------------------------------------------------------------------------
   8.178 +// _compareVertex() - Comparator for the vertex sorting.
   8.179 +//-----------------------------------------------------------------------------
   8.180 +static int _compareVertex(const void * elem1, const void * elem2)
   8.181 +{
   8.182 +  _CTMsortvertex * v1 = (_CTMsortvertex *) elem1;
   8.183 +  _CTMsortvertex * v2 = (_CTMsortvertex *) elem2;
   8.184 +  if(v1->mGridIndex != v2->mGridIndex)
   8.185 +    return v1->mGridIndex - v2->mGridIndex;
   8.186 +  else if(v1->x < v2->x)
   8.187 +    return -1;
   8.188 +  else if(v1->x > v2->x)
   8.189 +    return 1;
   8.190 +  else
   8.191 +    return 0;
   8.192 +}
   8.193 +
   8.194 +//-----------------------------------------------------------------------------
   8.195 +// _ctmSortVertices() - Setup the vertex array. Assign each vertex to a grid
   8.196 +// box, and sort all vertices.
   8.197 +//-----------------------------------------------------------------------------
   8.198 +static void _ctmSortVertices(_CTMcontext * self, _CTMsortvertex * aSortVertices,
   8.199 +  _CTMgrid * aGrid)
   8.200 +{
   8.201 +  CTMuint i;
   8.202 +
   8.203 +  // Prepare sort vertex array
   8.204 +  for(i = 0; i < self->mVertexCount; ++ i)
   8.205 +  {
   8.206 +    // Store vertex properties in the sort vertex array
   8.207 +    aSortVertices[i].x = self->mVertices[i * 3];
   8.208 +    aSortVertices[i].mGridIndex = _ctmPointToGridIdx(aGrid, &self->mVertices[i * 3]);
   8.209 +    aSortVertices[i].mOriginalIndex = i;
   8.210 +  }
   8.211 +
   8.212 +  // Sort vertices. The elements are first sorted by their grid indices, and
   8.213 +  // scondly by their x coordinates.
   8.214 +  qsort((void *) aSortVertices, self->mVertexCount, sizeof(_CTMsortvertex), _compareVertex);
   8.215 +}
   8.216 +
   8.217 +//-----------------------------------------------------------------------------
   8.218 +// _ctmReIndexIndices() - Re-index all indices, based on the sorted vertices.
   8.219 +//-----------------------------------------------------------------------------
   8.220 +static int _ctmReIndexIndices(_CTMcontext * self, _CTMsortvertex * aSortVertices,
   8.221 +  CTMuint * aIndices)
   8.222 +{
   8.223 +  CTMuint i, * indexLUT;
   8.224 +
   8.225 +  // Create temporary lookup-array, O(n)
   8.226 +  indexLUT = (CTMuint *) malloc(sizeof(CTMuint) * self->mVertexCount);
   8.227 +  if(!indexLUT)
   8.228 +  {
   8.229 +    self->mError = CTM_OUT_OF_MEMORY;
   8.230 +    return CTM_FALSE;
   8.231 +  }
   8.232 +  for(i = 0; i < self->mVertexCount; ++ i)
   8.233 +    indexLUT[aSortVertices[i].mOriginalIndex] = i;
   8.234 +
   8.235 +  // Convert old indices to new indices, O(n)
   8.236 +  for(i = 0; i < self->mTriangleCount * 3; ++ i)
   8.237 +    aIndices[i] = indexLUT[self->mIndices[i]];
   8.238 +
   8.239 +  // Free temporary lookup-array
   8.240 +  free((void *) indexLUT);
   8.241 +
   8.242 +  return CTM_TRUE;
   8.243 +}
   8.244 +
   8.245 +//-----------------------------------------------------------------------------
   8.246 +// _compareTriangle() - Comparator for the triangle sorting.
   8.247 +//-----------------------------------------------------------------------------
   8.248 +static int _compareTriangle(const void * elem1, const void * elem2)
   8.249 +{
   8.250 +  CTMuint * tri1 = (CTMuint *) elem1;
   8.251 +  CTMuint * tri2 = (CTMuint *) elem2;
   8.252 +  if(tri1[0] != tri2[0])
   8.253 +    return tri1[0] - tri2[0];
   8.254 +  else
   8.255 +    return tri1[1] - tri2[1];
   8.256 +}
   8.257 +
   8.258 +//-----------------------------------------------------------------------------
   8.259 +// _ctmReArrangeTriangles() - Re-arrange all triangles for optimal
   8.260 +// compression.
   8.261 +//-----------------------------------------------------------------------------
   8.262 +static void _ctmReArrangeTriangles(_CTMcontext * self, CTMuint * aIndices)
   8.263 +{
   8.264 +  CTMuint * tri, tmp, i;
   8.265 +
   8.266 +  // Step 1: Make sure that the first index of each triangle is the smallest
   8.267 +  // one (rotate triangle nodes if necessary)
   8.268 +  for(i = 0; i < self->mTriangleCount; ++ i)
   8.269 +  {
   8.270 +    tri = &aIndices[i * 3];
   8.271 +    if((tri[1] < tri[0]) && (tri[1] < tri[2]))
   8.272 +    {
   8.273 +      tmp = tri[0];
   8.274 +      tri[0] = tri[1];
   8.275 +      tri[1] = tri[2];
   8.276 +      tri[2] = tmp;
   8.277 +    }
   8.278 +    else if((tri[2] < tri[0]) && (tri[2] < tri[1]))
   8.279 +    {
   8.280 +      tmp = tri[0];
   8.281 +      tri[0] = tri[2];
   8.282 +      tri[2] = tri[1];
   8.283 +      tri[1] = tmp;
   8.284 +    }
   8.285 +  }
   8.286 +
   8.287 +  // Step 2: Sort the triangles based on the first triangle index
   8.288 +  qsort((void *) aIndices, self->mTriangleCount, sizeof(CTMuint) * 3, _compareTriangle);
   8.289 +}
   8.290 +
   8.291 +//-----------------------------------------------------------------------------
   8.292 +// _ctmMakeIndexDeltas() - Calculate various forms of derivatives in order to
   8.293 +// reduce data entropy.
   8.294 +//-----------------------------------------------------------------------------
   8.295 +static void _ctmMakeIndexDeltas(_CTMcontext * self, CTMuint * aIndices)
   8.296 +{
   8.297 +  CTMint i;
   8.298 +  for(i = self->mTriangleCount - 1; i >= 0; -- i)
   8.299 +  {
   8.300 +    // Step 1: Calculate delta from second triangle index to the previous
   8.301 +    // second triangle index, if the previous triangle shares the same first
   8.302 +    // index, otherwise calculate the delta to the first triangle index
   8.303 +    if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3]))
   8.304 +      aIndices[i * 3 + 1] -= aIndices[(i - 1) * 3 + 1];
   8.305 +    else
   8.306 +      aIndices[i * 3 + 1] -= aIndices[i * 3];
   8.307 +
   8.308 +    // Step 2: Calculate delta from third triangle index to the first triangle
   8.309 +    // index
   8.310 +    aIndices[i * 3 + 2] -= aIndices[i * 3];
   8.311 +
   8.312 +    // Step 3: Calculate derivative of the first triangle index
   8.313 +    if(i >= 1)
   8.314 +      aIndices[i * 3] -= aIndices[(i - 1) * 3];
   8.315 +  }
   8.316 +}
   8.317 +
   8.318 +//-----------------------------------------------------------------------------
   8.319 +// _ctmRestoreIndices() - Restore original indices (inverse derivative
   8.320 +// operation).
   8.321 +//-----------------------------------------------------------------------------
   8.322 +static void _ctmRestoreIndices(_CTMcontext * self, CTMuint * aIndices)
   8.323 +{
   8.324 +  CTMuint i;
   8.325 +
   8.326 +  for(i = 0; i < self->mTriangleCount; ++ i)
   8.327 +  {
   8.328 +    // Step 1: Reverse derivative of the first triangle index
   8.329 +    if(i >= 1)
   8.330 +      aIndices[i * 3] += aIndices[(i - 1) * 3];
   8.331 +
   8.332 +    // Step 2: Reverse delta from third triangle index to the first triangle
   8.333 +    // index
   8.334 +    aIndices[i * 3 + 2] += aIndices[i * 3];
   8.335 +
   8.336 +    // Step 3: Reverse delta from second triangle index to the previous
   8.337 +    // second triangle index, if the previous triangle shares the same first
   8.338 +    // index, otherwise reverse the delta to the first triangle index
   8.339 +    if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3]))
   8.340 +      aIndices[i * 3 + 1] += aIndices[(i - 1) * 3 + 1];
   8.341 +    else
   8.342 +      aIndices[i * 3 + 1] += aIndices[i * 3];
   8.343 +  }
   8.344 +}
   8.345 +
   8.346 +//-----------------------------------------------------------------------------
   8.347 +// _ctmMakeVertexDeltas() - Calculate various forms of derivatives in order to
   8.348 +// reduce data entropy.
   8.349 +//-----------------------------------------------------------------------------
   8.350 +static void _ctmMakeVertexDeltas(_CTMcontext * self, CTMint * aIntVertices,
   8.351 +  _CTMsortvertex * aSortVertices, _CTMgrid * aGrid)
   8.352 +{
   8.353 +  CTMuint i, gridIdx, prevGridIndex, oldIdx;
   8.354 +  CTMfloat gridOrigin[3], scale;
   8.355 +  CTMint deltaX, prevDeltaX;
   8.356 +
   8.357 +  // Vertex scaling factor
   8.358 +  scale = 1.0f / self->mVertexPrecision;
   8.359 +
   8.360 +  prevGridIndex = 0x7fffffff;
   8.361 +  prevDeltaX = 0;
   8.362 +  for(i = 0; i < self->mVertexCount; ++ i)
   8.363 +  {
   8.364 +    // Get grid box origin
   8.365 +    gridIdx = aSortVertices[i].mGridIndex;
   8.366 +    _ctmGridIdxToPoint(aGrid, gridIdx, gridOrigin);
   8.367 +
   8.368 +    // Get old vertex coordinate index (before vertex sorting)
   8.369 +    oldIdx = aSortVertices[i].mOriginalIndex;
   8.370 +
   8.371 +    // Store delta to the grid box origin in the integer vertex array. For the
   8.372 +    // X axis (which is sorted) we also do the delta to the previous coordinate
   8.373 +    // in the box.
   8.374 +    deltaX = (CTMint) floorf(scale * (self->mVertices[oldIdx * 3] - gridOrigin[0]) + 0.5f);
   8.375 +    if(gridIdx == prevGridIndex)
   8.376 +      aIntVertices[i * 3] = deltaX - prevDeltaX;
   8.377 +    else
   8.378 +      aIntVertices[i * 3] = deltaX;
   8.379 +    aIntVertices[i * 3 + 1] = (CTMint) floorf(scale * (self->mVertices[oldIdx * 3 + 1] - gridOrigin[1]) + 0.5f);
   8.380 +    aIntVertices[i * 3 + 2] = (CTMint) floorf(scale * (self->mVertices[oldIdx * 3 + 2] - gridOrigin[2]) + 0.5f);
   8.381 +
   8.382 +    prevGridIndex = gridIdx;
   8.383 +    prevDeltaX = deltaX;
   8.384 +  }
   8.385 +}
   8.386 +
   8.387 +//-----------------------------------------------------------------------------
   8.388 +// _ctmRestoreVertices() - Calculate inverse derivatives of the vertices.
   8.389 +//-----------------------------------------------------------------------------
   8.390 +static void _ctmRestoreVertices(_CTMcontext * self, CTMint * aIntVertices,
   8.391 +  CTMuint * aGridIndices, _CTMgrid * aGrid, CTMfloat * aVertices)
   8.392 +{
   8.393 +  CTMuint i, gridIdx, prevGridIndex;
   8.394 +  CTMfloat gridOrigin[3], scale;
   8.395 +  CTMint deltaX, prevDeltaX;
   8.396 +
   8.397 +  scale = self->mVertexPrecision;
   8.398 +
   8.399 +  prevGridIndex = 0x7fffffff;
   8.400 +  prevDeltaX = 0;
   8.401 +  for(i = 0; i < self->mVertexCount; ++ i)
   8.402 +  {
   8.403 +    // Get grid box origin
   8.404 +    gridIdx = aGridIndices[i];
   8.405 +    _ctmGridIdxToPoint(aGrid, gridIdx, gridOrigin);
   8.406 +
   8.407 +    // Restore original point
   8.408 +    deltaX = aIntVertices[i * 3];
   8.409 +    if(gridIdx == prevGridIndex)
   8.410 +      deltaX += prevDeltaX;
   8.411 +    aVertices[i * 3] = scale * deltaX + gridOrigin[0];
   8.412 +    aVertices[i * 3 + 1] = scale * aIntVertices[i * 3 + 1] + gridOrigin[1];
   8.413 +    aVertices[i * 3 + 2] = scale * aIntVertices[i * 3 + 2] + gridOrigin[2];
   8.414 +
   8.415 +    prevGridIndex = gridIdx;
   8.416 +    prevDeltaX = deltaX;
   8.417 +  }
   8.418 +}
   8.419 +
   8.420 +//-----------------------------------------------------------------------------
   8.421 +// _ctmCalcSmoothNormals() - Calculate the smooth normals for a given mesh.
   8.422 +// These are used as the nominal normals for normal deltas & reconstruction.
   8.423 +//-----------------------------------------------------------------------------
   8.424 +static void _ctmCalcSmoothNormals(_CTMcontext * self, CTMfloat * aVertices,
   8.425 +  CTMuint * aIndices, CTMfloat * aSmoothNormals)
   8.426 +{
   8.427 +  CTMuint i, j, k, tri[3];
   8.428 +  CTMfloat len;
   8.429 +  CTMfloat v1[3], v2[3], n[3];
   8.430 +
   8.431 +  // Clear smooth normals array
   8.432 +  for(i = 0; i < 3 * self->mVertexCount; ++ i)
   8.433 +    aSmoothNormals[i] = 0.0f;
   8.434 +
   8.435 +  // Calculate sums of all neigbouring triangle normals for each vertex
   8.436 +  for(i = 0; i < self->mTriangleCount; ++ i)
   8.437 +  {
   8.438 +    // Get triangle corner indices
   8.439 +    for(j = 0; j < 3; ++ j)
   8.440 +      tri[j] = aIndices[i * 3 + j];
   8.441 +
   8.442 +    // Calculate the normalized cross product of two triangle edges (i.e. the
   8.443 +    // flat triangle normal)
   8.444 +    for(j = 0; j < 3; ++ j)
   8.445 +    {
   8.446 +      v1[j] = aVertices[tri[1] * 3 + j] - aVertices[tri[0] * 3 + j];
   8.447 +      v2[j] = aVertices[tri[2] * 3 + j] - aVertices[tri[0] * 3 + j];
   8.448 +    }
   8.449 +    n[0] = v1[1] * v2[2] - v1[2] * v2[1];
   8.450 +    n[1] = v1[2] * v2[0] - v1[0] * v2[2];
   8.451 +    n[2] = v1[0] * v2[1] - v1[1] * v2[0];
   8.452 +    len = sqrtf(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
   8.453 +    if(len > 1e-10f)
   8.454 +      len = 1.0f / len;
   8.455 +    else
   8.456 +      len = 1.0f;
   8.457 +    for(j = 0; j < 3; ++ j)
   8.458 +      n[j] *= len;
   8.459 +
   8.460 +    // Add the flat normal to all three triangle vertices
   8.461 +    for(k = 0; k < 3; ++ k)
   8.462 +      for(j = 0; j < 3; ++ j)
   8.463 +        aSmoothNormals[tri[k] * 3 + j] += n[j];
   8.464 +  }
   8.465 +
   8.466 +  // Normalize the normal sums, which gives the unit length smooth normals
   8.467 +  for(i = 0; i < self->mVertexCount; ++ i)
   8.468 +  {
   8.469 +    len = sqrtf(aSmoothNormals[i * 3] * aSmoothNormals[i * 3] + 
   8.470 +                aSmoothNormals[i * 3 + 1] * aSmoothNormals[i * 3 + 1] +
   8.471 +                aSmoothNormals[i * 3 + 2] * aSmoothNormals[i * 3 + 2]);
   8.472 +    if(len > 1e-10f)
   8.473 +      len = 1.0f / len;
   8.474 +    else
   8.475 +      len = 1.0f;
   8.476 +    for(j = 0; j < 3; ++ j)
   8.477 +      aSmoothNormals[i * 3 + j] *= len;
   8.478 +  }
   8.479 +}
   8.480 +
   8.481 +//-----------------------------------------------------------------------------
   8.482 +// _ctmMakeNormalCoordSys() - Create an ortho-normalized coordinate system
   8.483 +// where the Z-axis is aligned with the given normal.
   8.484 +// Note 1: This function is central to how the compressed normal data is
   8.485 +//  interpreted, and it can not be changed (mathematically) without making the
   8.486 +//  coder/decoder incompatible with other versions of the library!
   8.487 +// Note 2: Since we do this for every single normal, this routine needs to be
   8.488 +//  fast. The current implementation uses: 12 MUL, 1 DIV, 1 SQRT, ~6 ADD.
   8.489 +//-----------------------------------------------------------------------------
   8.490 +static void _ctmMakeNormalCoordSys(CTMfloat * aNormal, CTMfloat * aBasisAxes)
   8.491 +{
   8.492 +  CTMfloat len, * x, * y, * z;
   8.493 +  CTMuint i;
   8.494 +
   8.495 +  // Pointers to the basis axes (aBasisAxes is a 3x3 matrix)
   8.496 +  x = aBasisAxes;
   8.497 +  y = &aBasisAxes[3];
   8.498 +  z = &aBasisAxes[6];
   8.499 +
   8.500 +  // Z = normal (must be unit length!)
   8.501 +  for(i = 0; i < 3; ++ i)
   8.502 +    z[i] = aNormal[i];
   8.503 +
   8.504 +  // Calculate a vector that is guaranteed to be orthogonal to the normal, non-
   8.505 +  // zero, and a continuous function of the normal (no discrete jumps):
   8.506 +  // X = (0,0,1) x normal + (1,0,0) x normal
   8.507 +  x[0] =  -aNormal[1];
   8.508 +  x[1] =  aNormal[0] - aNormal[2];
   8.509 +  x[2] =  aNormal[1];
   8.510 +
   8.511 +  // Normalize the new X axis (note: |x[2]| = |x[0]|)
   8.512 +  len = sqrtf(2.0 * x[0] * x[0] + x[1] * x[1]);
   8.513 +  if(len > 1.0e-20f)
   8.514 +  {
   8.515 +    len = 1.0f / len;
   8.516 +    x[0] *= len;
   8.517 +    x[1] *= len;
   8.518 +    x[2] *= len;
   8.519 +  }
   8.520 +
   8.521 +  // Let Y = Z x X  (no normalization needed, since |Z| = |X| = 1)
   8.522 +  y[0] = z[1] * x[2] - z[2] * x[1];
   8.523 +  y[1] = z[2] * x[0] - z[0] * x[2];
   8.524 +  y[2] = z[0] * x[1] - z[1] * x[0];
   8.525 +}
   8.526 +
   8.527 +//-----------------------------------------------------------------------------
   8.528 +// _ctmMakeNormalDeltas() - Convert the normals to a new coordinate system:
   8.529 +// magnitude, phi, theta (relative to predicted smooth normals).
   8.530 +//-----------------------------------------------------------------------------
   8.531 +static CTMint _ctmMakeNormalDeltas(_CTMcontext * self, CTMint * aIntNormals,
   8.532 +  CTMfloat * aVertices, CTMuint * aIndices, _CTMsortvertex * aSortVertices)
   8.533 +{
   8.534 +  CTMuint i, j, oldIdx, intPhi;
   8.535 +  CTMfloat magn, phi, theta, scale, thetaScale;
   8.536 +  CTMfloat * smoothNormals, n[3], n2[3], basisAxes[9];
   8.537 +
   8.538 +  // Allocate temporary memory for the nominal vertex normals
   8.539 +  smoothNormals = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * self->mVertexCount);
   8.540 +  if(!smoothNormals)
   8.541 +  {
   8.542 +    self->mError = CTM_OUT_OF_MEMORY;
   8.543 +    return CTM_FALSE;
   8.544 +  }
   8.545 +
   8.546 +  // Calculate smooth normals (Note: aVertices and aIndices use the sorted
   8.547 +  // index space, so smoothNormals will too)
   8.548 +  _ctmCalcSmoothNormals(self, aVertices, aIndices, smoothNormals);
   8.549 +
   8.550 +  // Normal scaling factor
   8.551 +  scale = 1.0f / self->mNormalPrecision;
   8.552 +
   8.553 +  for(i = 0; i < self->mVertexCount; ++ i)
   8.554 +  {
   8.555 +    // Get old normal index (before vertex sorting)
   8.556 +    oldIdx = aSortVertices[i].mOriginalIndex;
   8.557 +
   8.558 +    // Calculate normal magnitude (should always be 1.0 for unit length normals)
   8.559 +    magn = sqrtf(self->mNormals[oldIdx * 3] * self->mNormals[oldIdx * 3] +
   8.560 +                 self->mNormals[oldIdx * 3 + 1] * self->mNormals[oldIdx * 3 + 1] +
   8.561 +                 self->mNormals[oldIdx * 3 + 2] * self->mNormals[oldIdx * 3 + 2]);
   8.562 +    if(magn < 1e-10f)
   8.563 +      magn = 1.0f;
   8.564 +
   8.565 +    // Invert magnitude if the normal is negative compared to the predicted
   8.566 +    // smooth normal
   8.567 +    if((smoothNormals[i * 3] * self->mNormals[oldIdx * 3] +
   8.568 +        smoothNormals[i * 3 + 1] * self->mNormals[oldIdx * 3 + 1] +
   8.569 +        smoothNormals[i * 3 + 2] * self->mNormals[oldIdx * 3 + 2]) < 0.0f)
   8.570 +      magn = -magn;
   8.571 +
   8.572 +    // Store the magnitude in the first element of the three normal elements
   8.573 +    aIntNormals[i * 3] = (CTMint) floorf(scale * magn + 0.5f);
   8.574 +
   8.575 +    // Normalize the normal (1 / magn) - and flip it if magn < 0
   8.576 +    magn = 1.0f / magn;
   8.577 +    for(j = 0; j < 3; ++ j)
   8.578 +      n[j] = self->mNormals[oldIdx * 3 + j] * magn;
   8.579 +
   8.580 +    // Convert the normal to angular representation (phi, theta) in a coordinate
   8.581 +    // system where the nominal (smooth) normal is the Z-axis
   8.582 +    _ctmMakeNormalCoordSys(&smoothNormals[i * 3], basisAxes);
   8.583 +    for(j = 0; j < 3; ++ j)
   8.584 +      n2[j] = basisAxes[j * 3] * n[0] +
   8.585 +              basisAxes[j * 3 + 1] * n[1] +
   8.586 +              basisAxes[j * 3 + 2] * n[2];
   8.587 +    if(n2[2] >= 1.0f)
   8.588 +      phi = 0.0f;
   8.589 +    else
   8.590 +      phi = acosf(n2[2]);
   8.591 +    theta = atan2f(n2[1], n2[0]);
   8.592 +
   8.593 +    // Round phi and theta (spherical coordinates) to integers. Note: We let the
   8.594 +    // theta resolution vary with the x/y circumference (roughly phi).
   8.595 +    intPhi = (CTMint) floorf(phi * (scale / (0.5f * PI)) + 0.5f);
   8.596 +    if(intPhi == 0)
   8.597 +      thetaScale = 0.0f;
   8.598 +    else if(intPhi <= 4)
   8.599 +      thetaScale = 2.0f / PI;
   8.600 +    else
   8.601 +      thetaScale = ((CTMfloat) intPhi) / (2.0f * PI);
   8.602 +    aIntNormals[i * 3 + 1] = intPhi;
   8.603 +    aIntNormals[i * 3 + 2] = (CTMint) floorf((theta + PI) * thetaScale + 0.5f);
   8.604 +  }
   8.605 +
   8.606 +  // Free temporary resources
   8.607 +  free(smoothNormals);
   8.608 +
   8.609 +  return CTM_TRUE;
   8.610 +}
   8.611 +
   8.612 +//-----------------------------------------------------------------------------
   8.613 +// _ctmRestoreNormals() - Convert the normals back to cartesian coordinates.
   8.614 +//-----------------------------------------------------------------------------
   8.615 +static CTMint _ctmRestoreNormals(_CTMcontext * self, CTMint * aIntNormals)
   8.616 +{
   8.617 +  CTMuint i, j, intPhi;
   8.618 +  CTMfloat magn, phi, theta, scale, thetaScale;
   8.619 +  CTMfloat * smoothNormals, n[3], n2[3], basisAxes[9];
   8.620 +
   8.621 +  // Allocate temporary memory for the nominal vertex normals
   8.622 +  smoothNormals = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * self->mVertexCount);
   8.623 +  if(!smoothNormals)
   8.624 +  {
   8.625 +    self->mError = CTM_OUT_OF_MEMORY;
   8.626 +    return CTM_FALSE;
   8.627 +  }
   8.628 +
   8.629 +  // Calculate smooth normals (nominal normals)
   8.630 +  _ctmCalcSmoothNormals(self, self->mVertices, self->mIndices, smoothNormals);
   8.631 +
   8.632 +  // Normal scaling factor
   8.633 +  scale = self->mNormalPrecision;
   8.634 +
   8.635 +  for(i = 0; i < self->mVertexCount; ++ i)
   8.636 +  {
   8.637 +    // Get the normal magnitude from the first of the three normal elements
   8.638 +    magn = aIntNormals[i * 3] * scale;
   8.639 +
   8.640 +    // Get phi and theta (spherical coordinates, relative to the smooth normal).
   8.641 +    intPhi = aIntNormals[i * 3 + 1];
   8.642 +    phi = intPhi * (0.5f * PI) * scale;
   8.643 +    if(intPhi == 0)
   8.644 +      thetaScale = 0.0f;
   8.645 +    else if(intPhi <= 4)
   8.646 +      thetaScale = PI / 2.0f;
   8.647 +    else
   8.648 +      thetaScale = (2.0f * PI) / ((CTMfloat) intPhi);
   8.649 +    theta = aIntNormals[i * 3 + 2] * thetaScale - PI;
   8.650 +
   8.651 +    // Convert the normal from the angular representation (phi, theta) back to
   8.652 +    // cartesian coordinates
   8.653 +    n2[0] = sinf(phi) * cosf(theta);
   8.654 +    n2[1] = sinf(phi) * sinf(theta);
   8.655 +    n2[2] = cosf(phi);
   8.656 +    _ctmMakeNormalCoordSys(&smoothNormals[i * 3], basisAxes);
   8.657 +    for(j = 0; j < 3; ++ j)
   8.658 +      n[j] = basisAxes[j] * n2[0] +
   8.659 +             basisAxes[3 + j] * n2[1] +
   8.660 +             basisAxes[6 + j] * n2[2];
   8.661 +
   8.662 +    // Apply normal magnitude, and output to the normals array
   8.663 +    for(j = 0; j < 3; ++ j)
   8.664 +      self->mNormals[i * 3 + j] = n[j] * magn;
   8.665 +  }
   8.666 +
   8.667 +  // Free temporary resources
   8.668 +  free(smoothNormals);
   8.669 +
   8.670 +  return CTM_TRUE;
   8.671 +}
   8.672 +
   8.673 +//-----------------------------------------------------------------------------
   8.674 +// _ctmMakeUVCoordDeltas() - Calculate various forms of derivatives in order
   8.675 +// to reduce data entropy.
   8.676 +//-----------------------------------------------------------------------------
   8.677 +static void _ctmMakeUVCoordDeltas(_CTMcontext * self, _CTMfloatmap * aMap,
   8.678 +  CTMint * aIntUVCoords, _CTMsortvertex * aSortVertices)
   8.679 +{
   8.680 +  CTMuint i, oldIdx;
   8.681 +  CTMint u, v, prevU, prevV;
   8.682 +  CTMfloat scale;
   8.683 +
   8.684 +  // UV coordinate scaling factor
   8.685 +  scale = 1.0f / aMap->mPrecision;
   8.686 +
   8.687 +  prevU = prevV = 0;
   8.688 +  for(i = 0; i < self->mVertexCount; ++ i)
   8.689 +  {
   8.690 +    // Get old UV coordinate index (before vertex sorting)
   8.691 +    oldIdx = aSortVertices[i].mOriginalIndex;
   8.692 +
   8.693 +    // Convert to fixed point
   8.694 +    u = (CTMint) floorf(scale * aMap->mValues[oldIdx * 2] + 0.5f);
   8.695 +    v = (CTMint) floorf(scale * aMap->mValues[oldIdx * 2 + 1] + 0.5f);
   8.696 +
   8.697 +    // Calculate delta and store it in the converted array. NOTE: Here we rely
   8.698 +    // on the fact that vertices are sorted, and usually close to each other,
   8.699 +    // which means that UV coordinates should also be close to each other...
   8.700 +    aIntUVCoords[i * 2] = u - prevU;
   8.701 +    aIntUVCoords[i * 2 + 1] = v - prevV;
   8.702 +
   8.703 +    prevU = u;
   8.704 +    prevV = v;
   8.705 +  }
   8.706 +}
   8.707 +
   8.708 +//-----------------------------------------------------------------------------
   8.709 +// _ctmRestoreUVCoords() - Calculate inverse derivatives of the UV
   8.710 +// coordinates.
   8.711 +//-----------------------------------------------------------------------------
   8.712 +static void _ctmRestoreUVCoords(_CTMcontext * self, _CTMfloatmap * aMap,
   8.713 +  CTMint * aIntUVCoords)
   8.714 +{
   8.715 +  CTMuint i;
   8.716 +  CTMint u, v, prevU, prevV;
   8.717 +  CTMfloat scale;
   8.718 +
   8.719 +  // UV coordinate scaling factor
   8.720 +  scale = aMap->mPrecision;
   8.721 +
   8.722 +  prevU = prevV = 0;
   8.723 +  for(i = 0; i < self->mVertexCount; ++ i)
   8.724 +  {
   8.725 +    // Calculate inverse delta
   8.726 +    u = aIntUVCoords[i * 2] + prevU;
   8.727 +    v = aIntUVCoords[i * 2 + 1] + prevV;
   8.728 +
   8.729 +    // Convert to floating point
   8.730 +    aMap->mValues[i * 2] = (CTMfloat) u * scale;
   8.731 +    aMap->mValues[i * 2 + 1] = (CTMfloat) v * scale;
   8.732 +
   8.733 +    prevU = u;
   8.734 +    prevV = v;
   8.735 +  }
   8.736 +}
   8.737 +
   8.738 +//-----------------------------------------------------------------------------
   8.739 +// _ctmMakeAttribDeltas() - Calculate various forms of derivatives in order
   8.740 +// to reduce data entropy.
   8.741 +//-----------------------------------------------------------------------------
   8.742 +static void _ctmMakeAttribDeltas(_CTMcontext * self, _CTMfloatmap * aMap,
   8.743 +  CTMint * aIntAttribs, _CTMsortvertex * aSortVertices)
   8.744 +{
   8.745 +  CTMuint i, j, oldIdx;
   8.746 +  CTMint value[4], prev[4];
   8.747 +  CTMfloat scale;
   8.748 +
   8.749 +  // Attribute scaling factor
   8.750 +  scale = 1.0f / aMap->mPrecision;
   8.751 +
   8.752 +  for(j = 0; j < 4; ++ j)
   8.753 +    prev[j] = 0;
   8.754 +
   8.755 +  for(i = 0; i < self->mVertexCount; ++ i)
   8.756 +  {
   8.757 +    // Get old attribute index (before vertex sorting)
   8.758 +    oldIdx = aSortVertices[i].mOriginalIndex;
   8.759 +
   8.760 +    // Convert to fixed point, and calculate delta and store it in the converted
   8.761 +    // array. NOTE: Here we rely on the fact that vertices are sorted, and
   8.762 +    // usually close to each other, which means that attributes should also
   8.763 +    // be close to each other (and we assume that they somehow vary slowly with
   8.764 +    // the geometry)...
   8.765 +    for(j = 0; j < 4; ++ j)
   8.766 +    {
   8.767 +      value[j] = (CTMint) floorf(scale * aMap->mValues[oldIdx * 4 + j] + 0.5f);
   8.768 +      aIntAttribs[i * 4 + j] = value[j] - prev[j];
   8.769 +      prev[j] = value[j];
   8.770 +    }
   8.771 +  }
   8.772 +}
   8.773 +
   8.774 +//-----------------------------------------------------------------------------
   8.775 +// _ctmRestoreAttribs() - Calculate inverse derivatives of the vertex
   8.776 +// attributes.
   8.777 +//-----------------------------------------------------------------------------
   8.778 +static void _ctmRestoreAttribs(_CTMcontext * self, _CTMfloatmap * aMap,
   8.779 +  CTMint * aIntAttribs)
   8.780 +{
   8.781 +  CTMuint i, j;
   8.782 +  CTMint value[4], prev[4];
   8.783 +  CTMfloat scale;
   8.784 +
   8.785 +  // Attribute scaling factor
   8.786 +  scale = aMap->mPrecision;
   8.787 +
   8.788 +  for(j = 0; j < 4; ++ j)
   8.789 +    prev[j] = 0;
   8.790 +
   8.791 +  for(i = 0; i < self->mVertexCount; ++ i)
   8.792 +  {
   8.793 +    // Calculate inverse delta, and convert to floating point
   8.794 +    for(j = 0; j < 4; ++ j)
   8.795 +    {
   8.796 +      value[j] = aIntAttribs[i * 4 + j] + prev[j];
   8.797 +      aMap->mValues[i * 4 + j] = (CTMfloat) value[j] * scale;
   8.798 +      prev[j] = value[j];
   8.799 +    }
   8.800 +  }
   8.801 +}
   8.802 +
   8.803 +//-----------------------------------------------------------------------------
   8.804 +// _ctmCompressMesh_MG2() - Compress the mesh that is stored in the CTM
   8.805 +// context, and write it the the output stream in the CTM context.
   8.806 +//-----------------------------------------------------------------------------
   8.807 +int _ctmCompressMesh_MG2(_CTMcontext * self)
   8.808 +{
   8.809 +  _CTMgrid grid;
   8.810 +  _CTMsortvertex * sortVertices;
   8.811 +  _CTMfloatmap * map;
   8.812 +  CTMuint * indices, * deltaIndices, * gridIndices;
   8.813 +  CTMint * intVertices, * intNormals, * intUVCoords, * intAttribs;
   8.814 +  CTMfloat * restoredVertices;
   8.815 +  CTMuint i;
   8.816 +
   8.817 +#ifdef __DEBUG_
   8.818 +  printf("COMPRESSION METHOD: MG2\n");
   8.819 +#endif
   8.820 +
   8.821 +  // Setup 3D space subdivision grid
   8.822 +  _ctmSetupGrid(self, &grid);
   8.823 +
   8.824 +  // Write MG2-specific header information to the stream
   8.825 +  _ctmStreamWrite(self, (void *) "MG2H", 4);
   8.826 +  _ctmStreamWriteFLOAT(self, self->mVertexPrecision);
   8.827 +  _ctmStreamWriteFLOAT(self, self->mNormalPrecision);
   8.828 +  _ctmStreamWriteFLOAT(self, grid.mMin[0]);
   8.829 +  _ctmStreamWriteFLOAT(self, grid.mMin[1]);
   8.830 +  _ctmStreamWriteFLOAT(self, grid.mMin[2]);
   8.831 +  _ctmStreamWriteFLOAT(self, grid.mMax[0]);
   8.832 +  _ctmStreamWriteFLOAT(self, grid.mMax[1]);
   8.833 +  _ctmStreamWriteFLOAT(self, grid.mMax[2]);
   8.834 +  _ctmStreamWriteUINT(self, grid.mDivision[0]);
   8.835 +  _ctmStreamWriteUINT(self, grid.mDivision[1]);
   8.836 +  _ctmStreamWriteUINT(self, grid.mDivision[2]);
   8.837 +
   8.838 +  // Prepare (sort) vertices
   8.839 +  sortVertices = (_CTMsortvertex *) malloc(sizeof(_CTMsortvertex) * self->mVertexCount);
   8.840 +  if(!sortVertices)
   8.841 +  {
   8.842 +    self->mError = CTM_OUT_OF_MEMORY;
   8.843 +    return CTM_FALSE;
   8.844 +  }
   8.845 +  _ctmSortVertices(self, sortVertices, &grid);
   8.846 +
   8.847 +  // Convert vertices to integers and calculate vertex deltas (entropy-reduction)
   8.848 +  intVertices = (CTMint *) malloc(sizeof(CTMint) * 3 * self->mVertexCount);
   8.849 +  if(!intVertices)
   8.850 +  {
   8.851 +    self->mError = CTM_OUT_OF_MEMORY;
   8.852 +    free((void *) sortVertices);
   8.853 +    return CTM_FALSE;
   8.854 +  }
   8.855 +  _ctmMakeVertexDeltas(self, intVertices, sortVertices, &grid);
   8.856 +
   8.857 +  // Write vertices
   8.858 +#ifdef __DEBUG_
   8.859 +  printf("Vertices: ");
   8.860 +#endif
   8.861 +  _ctmStreamWrite(self, (void *) "VERT", 4);
   8.862 +  if(!_ctmStreamWritePackedInts(self, intVertices, self->mVertexCount, 3, CTM_FALSE))
   8.863 +  {
   8.864 +    free((void *) intVertices);
   8.865 +    free((void *) sortVertices);
   8.866 +    return CTM_FALSE;
   8.867 +  }
   8.868 +
   8.869 +  // Prepare grid indices (deltas)
   8.870 +  gridIndices = (CTMuint *) malloc(sizeof(CTMuint) * self->mVertexCount);
   8.871 +  if(!gridIndices)
   8.872 +  {
   8.873 +    self->mError = CTM_OUT_OF_MEMORY;
   8.874 +    free((void *) intVertices);
   8.875 +    free((void *) sortVertices);
   8.876 +    return CTM_FALSE;
   8.877 +  }
   8.878 +  gridIndices[0] = sortVertices[0].mGridIndex;
   8.879 +  for(i = 1; i < self->mVertexCount; ++ i)
   8.880 +    gridIndices[i] = sortVertices[i].mGridIndex - sortVertices[i - 1].mGridIndex;
   8.881 +  
   8.882 +  // Write grid indices
   8.883 +#ifdef __DEBUG_
   8.884 +  printf("Grid indices: ");
   8.885 +#endif
   8.886 +  _ctmStreamWrite(self, (void *) "GIDX", 4);
   8.887 +  if(!_ctmStreamWritePackedInts(self, (CTMint *) gridIndices, self->mVertexCount, 1, CTM_FALSE))
   8.888 +  {
   8.889 +    free((void *) gridIndices);
   8.890 +    free((void *) intVertices);
   8.891 +    free((void *) sortVertices);
   8.892 +    return CTM_FALSE;
   8.893 +  }
   8.894 +
   8.895 +  // Calculate the result of the compressed -> decompressed vertices, in order
   8.896 +  // to use the same vertex data for calculating nominal normals as the
   8.897 +  // decompression routine (i.e. compensate for the vertex error when
   8.898 +  // calculating the normals)
   8.899 +  restoredVertices = (CTMfloat *) malloc(sizeof(CTMfloat) * 3 * self->mVertexCount);
   8.900 +  if(!restoredVertices)
   8.901 +  {
   8.902 +    self->mError = CTM_OUT_OF_MEMORY;
   8.903 +    free((void *) gridIndices);
   8.904 +    free((void *) intVertices);
   8.905 +    free((void *) sortVertices);
   8.906 +    return CTM_FALSE;
   8.907 +  }
   8.908 +  for(i = 1; i < self->mVertexCount; ++ i)
   8.909 +    gridIndices[i] += gridIndices[i - 1];
   8.910 +  _ctmRestoreVertices(self, intVertices, gridIndices, &grid, restoredVertices);
   8.911 +
   8.912 +  // Free temporary resources
   8.913 +  free((void *) gridIndices);
   8.914 +  free((void *) intVertices);
   8.915 +
   8.916 +  // Perpare (sort) indices
   8.917 +  indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3);
   8.918 +  if(!indices)
   8.919 +  {
   8.920 +    self->mError = CTM_OUT_OF_MEMORY;
   8.921 +    free((void *) restoredVertices);
   8.922 +    free((void *) sortVertices);
   8.923 +    return CTM_FALSE;
   8.924 +  }
   8.925 +  if(!_ctmReIndexIndices(self, sortVertices, indices))
   8.926 +  {
   8.927 +    free((void *) indices);
   8.928 +    free((void *) restoredVertices);
   8.929 +    free((void *) sortVertices);
   8.930 +    return CTM_FALSE;
   8.931 +  }
   8.932 +  _ctmReArrangeTriangles(self, indices);
   8.933 +
   8.934 +  // Calculate index deltas (entropy-reduction)
   8.935 +  deltaIndices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3);
   8.936 +  if(!indices)
   8.937 +  {
   8.938 +    self->mError = CTM_OUT_OF_MEMORY;
   8.939 +    free((void *) indices);
   8.940 +    free((void *) restoredVertices);
   8.941 +    free((void *) sortVertices);
   8.942 +    return CTM_FALSE;
   8.943 +  }
   8.944 +  for(i = 0; i < self->mTriangleCount * 3; ++ i)
   8.945 +    deltaIndices[i] = indices[i];
   8.946 +  _ctmMakeIndexDeltas(self, deltaIndices);
   8.947 +
   8.948 +  // Write triangle indices
   8.949 +#ifdef __DEBUG_
   8.950 +  printf("Indices: ");
   8.951 +#endif
   8.952 +  _ctmStreamWrite(self, (void *) "INDX", 4);
   8.953 +  if(!_ctmStreamWritePackedInts(self, (CTMint *) deltaIndices, self->mTriangleCount, 3, CTM_FALSE))
   8.954 +  {
   8.955 +    free((void *) deltaIndices);
   8.956 +    free((void *) indices);
   8.957 +    free((void *) restoredVertices);
   8.958 +    free((void *) sortVertices);
   8.959 +    return CTM_FALSE;
   8.960 +  }
   8.961 +
   8.962 +  // Free temporary data for the indices
   8.963 +  free((void *) deltaIndices);
   8.964 +
   8.965 +  if(self->mNormals)
   8.966 +  {
   8.967 +    // Convert normals to integers and calculate deltas (entropy-reduction)
   8.968 +    intNormals = (CTMint *) malloc(sizeof(CTMint) * 3 * self->mVertexCount);
   8.969 +    if(!intNormals)
   8.970 +    {
   8.971 +      self->mError = CTM_OUT_OF_MEMORY;
   8.972 +      free((void *) indices);
   8.973 +      free((void *) restoredVertices);
   8.974 +      free((void *) sortVertices);
   8.975 +      return CTM_FALSE;
   8.976 +    }
   8.977 +    if(!_ctmMakeNormalDeltas(self, intNormals, restoredVertices, indices, sortVertices))
   8.978 +    {
   8.979 +      free((void *) indices);
   8.980 +      free((void *) intNormals);
   8.981 +      free((void *) restoredVertices);
   8.982 +      free((void *) sortVertices);
   8.983 +      return CTM_FALSE;
   8.984 +    }
   8.985 +
   8.986 +    // Write normals
   8.987 +#ifdef __DEBUG_
   8.988 +    printf("Normals: ");
   8.989 +#endif
   8.990 +    _ctmStreamWrite(self, (void *) "NORM", 4);
   8.991 +    if(!_ctmStreamWritePackedInts(self, intNormals, self->mVertexCount, 3, CTM_FALSE))
   8.992 +    {
   8.993 +      free((void *) indices);
   8.994 +      free((void *) intNormals);
   8.995 +      free((void *) restoredVertices);
   8.996 +      free((void *) sortVertices);
   8.997 +      return CTM_FALSE;
   8.998 +    }
   8.999 +
  8.1000 +    // Free temporary normal data
  8.1001 +    free((void *) intNormals);
  8.1002 +  }
  8.1003 +
  8.1004 +  // Free restored indices and vertices
  8.1005 +  free((void *) indices);
  8.1006 +  free((void *) restoredVertices);
  8.1007 +
  8.1008 +  // Write UV maps
  8.1009 +  map = self->mUVMaps;
  8.1010 +  while(map)
  8.1011 +  {
  8.1012 +    // Convert UV coordinates to integers and calculate deltas (entropy-reduction)
  8.1013 +    intUVCoords = (CTMint *) malloc(sizeof(CTMint) * 2 * self->mVertexCount);
  8.1014 +    if(!intUVCoords)
  8.1015 +    {
  8.1016 +      self->mError = CTM_OUT_OF_MEMORY;
  8.1017 +      free((void *) sortVertices);
  8.1018 +      return CTM_FALSE;
  8.1019 +    }
  8.1020 +    _ctmMakeUVCoordDeltas(self, map, intUVCoords, sortVertices);
  8.1021 +
  8.1022 +    // Write UV coordinates
  8.1023 +#ifdef __DEBUG_
  8.1024 +    printf("Texture coordinates (%s): ", map->mName ? map->mName : "no name");
  8.1025 +#endif
  8.1026 +    _ctmStreamWrite(self, (void *) "TEXC", 4);
  8.1027 +    _ctmStreamWriteSTRING(self, map->mName);
  8.1028 +    _ctmStreamWriteSTRING(self, map->mFileName);
  8.1029 +    _ctmStreamWriteFLOAT(self, map->mPrecision);
  8.1030 +    if(!_ctmStreamWritePackedInts(self, intUVCoords, self->mVertexCount, 2, CTM_TRUE))
  8.1031 +    {
  8.1032 +      free((void *) intUVCoords);
  8.1033 +      free((void *) sortVertices);
  8.1034 +      return CTM_FALSE;
  8.1035 +    }
  8.1036 +
  8.1037 +    // Free temporary UV coordinate data
  8.1038 +    free((void *) intUVCoords);
  8.1039 +
  8.1040 +    map = map->mNext;
  8.1041 +  }
  8.1042 +
  8.1043 +  // Write vertex attribute maps
  8.1044 +  map = self->mAttribMaps;
  8.1045 +  while(map)
  8.1046 +  {
  8.1047 +    // Convert vertex attributes to integers and calculate deltas (entropy-reduction)
  8.1048 +    intAttribs = (CTMint *) malloc(sizeof(CTMint) * 4 * self->mVertexCount);
  8.1049 +    if(!intAttribs)
  8.1050 +    {
  8.1051 +      self->mError = CTM_OUT_OF_MEMORY;
  8.1052 +      free((void *) sortVertices);
  8.1053 +      return CTM_FALSE;
  8.1054 +    }
  8.1055 +    _ctmMakeAttribDeltas(self, map, intAttribs, sortVertices);
  8.1056 +
  8.1057 +    // Write vertex attributes
  8.1058 +#ifdef __DEBUG_
  8.1059 +    printf("Vertex attributes (%s): ", map->mName ? map->mName : "no name");
  8.1060 +#endif
  8.1061 +    _ctmStreamWrite(self, (void *) "ATTR", 4);
  8.1062 +    _ctmStreamWriteSTRING(self, map->mName);
  8.1063 +    _ctmStreamWriteFLOAT(self, map->mPrecision);
  8.1064 +    if(!_ctmStreamWritePackedInts(self, intAttribs, self->mVertexCount, 4, CTM_TRUE))
  8.1065 +    {
  8.1066 +      free((void *) intAttribs);
  8.1067 +      free((void *) sortVertices);
  8.1068 +      return CTM_FALSE;
  8.1069 +    }
  8.1070 +
  8.1071 +    // Free temporary vertex attribute data
  8.1072 +    free((void *) intAttribs);
  8.1073 +
  8.1074 +    map = map->mNext;
  8.1075 +  }
  8.1076 +
  8.1077 +  // Free temporary data
  8.1078 +  free((void *) sortVertices);
  8.1079 +
  8.1080 +  return CTM_TRUE;
  8.1081 +}
  8.1082 +
  8.1083 +//-----------------------------------------------------------------------------
  8.1084 +// _ctmUncompressMesh_MG2() - Uncmpress the mesh from the input stream in the
  8.1085 +// CTM context, and store the resulting mesh in the CTM context.
  8.1086 +//-----------------------------------------------------------------------------
  8.1087 +int _ctmUncompressMesh_MG2(_CTMcontext * self)
  8.1088 +{
  8.1089 +  CTMuint * gridIndices, i;
  8.1090 +  CTMint * intVertices, * intNormals, * intUVCoords, * intAttribs;
  8.1091 +  _CTMfloatmap * map;
  8.1092 +  _CTMgrid grid;
  8.1093 +
  8.1094 +  // Read MG2-specific header information from the stream
  8.1095 +  if(_ctmStreamReadUINT(self) != FOURCC("MG2H"))
  8.1096 +  {
  8.1097 +    self->mError = CTM_BAD_FORMAT;
  8.1098 +    return CTM_FALSE;
  8.1099 +  }
  8.1100 +  self->mVertexPrecision = _ctmStreamReadFLOAT(self);
  8.1101 +  if(self->mVertexPrecision <= 0.0f)
  8.1102 +  {
  8.1103 +    self->mError = CTM_BAD_FORMAT;
  8.1104 +    return CTM_FALSE;
  8.1105 +  }
  8.1106 +  self->mNormalPrecision = _ctmStreamReadFLOAT(self);
  8.1107 +  if(self->mNormalPrecision <= 0.0f)
  8.1108 +  {
  8.1109 +    self->mError = CTM_BAD_FORMAT;
  8.1110 +    return CTM_FALSE;
  8.1111 +  }
  8.1112 +  grid.mMin[0] = _ctmStreamReadFLOAT(self);
  8.1113 +  grid.mMin[1] = _ctmStreamReadFLOAT(self);
  8.1114 +  grid.mMin[2] = _ctmStreamReadFLOAT(self);
  8.1115 +  grid.mMax[0] = _ctmStreamReadFLOAT(self);
  8.1116 +  grid.mMax[1] = _ctmStreamReadFLOAT(self);
  8.1117 +  grid.mMax[2] = _ctmStreamReadFLOAT(self);
  8.1118 +  if((grid.mMax[0] < grid.mMin[0]) ||
  8.1119 +     (grid.mMax[1] < grid.mMin[1]) ||
  8.1120 +     (grid.mMax[2] < grid.mMin[2]))
  8.1121 +  {
  8.1122 +    self->mError = CTM_BAD_FORMAT;
  8.1123 +    return CTM_FALSE;
  8.1124 +  }
  8.1125 +  grid.mDivision[0] = _ctmStreamReadUINT(self);
  8.1126 +  grid.mDivision[1] = _ctmStreamReadUINT(self);
  8.1127 +  grid.mDivision[2] = _ctmStreamReadUINT(self);
  8.1128 +  if((grid.mDivision[0] < 1) || (grid.mDivision[1] < 1) || (grid.mDivision[2] < 1))
  8.1129 +  {
  8.1130 +    self->mError = CTM_BAD_FORMAT;
  8.1131 +    return CTM_FALSE;
  8.1132 +  }
  8.1133 +
  8.1134 +  // Initialize 3D space subdivision grid
  8.1135 +  for(i = 0; i < 3; ++ i)
  8.1136 +    grid.mSize[i] = (grid.mMax[i] - grid.mMin[i]) / grid.mDivision[i];
  8.1137 +
  8.1138 +  // Read vertices
  8.1139 +  if(_ctmStreamReadUINT(self) != FOURCC("VERT"))
  8.1140 +  {
  8.1141 +    self->mError = CTM_BAD_FORMAT;
  8.1142 +    return CTM_FALSE;
  8.1143 +  }
  8.1144 +  intVertices = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 3);
  8.1145 +  if(!intVertices)
  8.1146 +  {
  8.1147 +    self->mError = CTM_OUT_OF_MEMORY;
  8.1148 +    return CTM_FALSE;
  8.1149 +  }
  8.1150 +  if(!_ctmStreamReadPackedInts(self, intVertices, self->mVertexCount, 3, CTM_FALSE))
  8.1151 +  {
  8.1152 +    free((void *) intVertices);
  8.1153 +    return CTM_FALSE;
  8.1154 +  }
  8.1155 +
  8.1156 +  // Read grid indices
  8.1157 +  if(_ctmStreamReadUINT(self) != FOURCC("GIDX"))
  8.1158 +  {
  8.1159 +    free((void *) intVertices);
  8.1160 +    self->mError = CTM_BAD_FORMAT;
  8.1161 +    return CTM_FALSE;
  8.1162 +  }
  8.1163 +  gridIndices = (CTMuint *) malloc(sizeof(CTMuint) * self->mVertexCount);
  8.1164 +  if(!gridIndices)
  8.1165 +  {
  8.1166 +    self->mError = CTM_OUT_OF_MEMORY;
  8.1167 +    free((void *) intVertices);
  8.1168 +    return CTM_FALSE;
  8.1169 +  }
  8.1170 +  if(!_ctmStreamReadPackedInts(self, (CTMint *) gridIndices, self->mVertexCount, 1, CTM_FALSE))
  8.1171 +  {
  8.1172 +    free((void *) gridIndices);
  8.1173 +    free((void *) intVertices);
  8.1174 +    return CTM_FALSE;
  8.1175 +  }
  8.1176 +
  8.1177 +  // Restore grid indices (deltas)
  8.1178 +  for(i = 1; i < self->mVertexCount; ++ i)
  8.1179 +    gridIndices[i] += gridIndices[i - 1];
  8.1180 +
  8.1181 +  // Restore vertices
  8.1182 +  _ctmRestoreVertices(self, intVertices, gridIndices, &grid, self->mVertices);
  8.1183 +
  8.1184 +  // Free temporary resources
  8.1185 +  free((void *) gridIndices);
  8.1186 +  free((void *) intVertices);
  8.1187 +
  8.1188 +  // Read triangle indices
  8.1189 +  if(_ctmStreamReadUINT(self) != FOURCC("INDX"))
  8.1190 +  {
  8.1191 +    self->mError = CTM_BAD_FORMAT;
  8.1192 +    return CTM_FALSE;
  8.1193 +  }
  8.1194 +  if(!_ctmStreamReadPackedInts(self, (CTMint *) self->mIndices, self->mTriangleCount, 3, CTM_FALSE))
  8.1195 +    return CTM_FALSE;
  8.1196 +
  8.1197 +  // Restore indices
  8.1198 +  _ctmRestoreIndices(self, self->mIndices);
  8.1199 +
  8.1200 +  // Check that all indices are within range
  8.1201 +  for(i = 0; i < (self->mTriangleCount * 3); ++ i)
  8.1202 +  {
  8.1203 +    if(self->mIndices[i] >= self->mVertexCount)
  8.1204 +    {
  8.1205 +      self->mError = CTM_INVALID_MESH;
  8.1206 +      return CTM_FALSE;
  8.1207 +    }
  8.1208 +  }
  8.1209 +
  8.1210 +  // Read normals
  8.1211 +  if(self->mNormals)
  8.1212 +  {
  8.1213 +    intNormals = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 3);
  8.1214 +    if(!intNormals)
  8.1215 +    {
  8.1216 +      self->mError = CTM_OUT_OF_MEMORY;
  8.1217 +      return CTM_FALSE;
  8.1218 +    }
  8.1219 +    if(_ctmStreamReadUINT(self) != FOURCC("NORM"))
  8.1220 +    {
  8.1221 +      self->mError = CTM_BAD_FORMAT;
  8.1222 +      free((void *) intNormals);
  8.1223 +      return CTM_FALSE;
  8.1224 +    }
  8.1225 +    if(!_ctmStreamReadPackedInts(self, intNormals, self->mVertexCount, 3, CTM_FALSE))
  8.1226 +    {
  8.1227 +      free((void *) intNormals);
  8.1228 +      return CTM_FALSE;
  8.1229 +    }
  8.1230 +
  8.1231 +    // Restore normals
  8.1232 +    if(!_ctmRestoreNormals(self, intNormals))
  8.1233 +    {
  8.1234 +      free((void *) intNormals);
  8.1235 +      return CTM_FALSE;
  8.1236 +    }
  8.1237 +
  8.1238 +    // Free temporary normals data
  8.1239 +    free((void *) intNormals);
  8.1240 +  }
  8.1241 +
  8.1242 +  // Read UV maps
  8.1243 +  map = self->mUVMaps;
  8.1244 +  while(map)
  8.1245 +  {
  8.1246 +    intUVCoords = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 2);
  8.1247 +    if(!intUVCoords)
  8.1248 +    {
  8.1249 +      self->mError = CTM_OUT_OF_MEMORY;
  8.1250 +      return CTM_FALSE;
  8.1251 +    }
  8.1252 +    if(_ctmStreamReadUINT(self) != FOURCC("TEXC"))
  8.1253 +    {
  8.1254 +      self->mError = CTM_BAD_FORMAT;
  8.1255 +      free((void *) intUVCoords);
  8.1256 +      return CTM_FALSE;
  8.1257 +    }
  8.1258 +    _ctmStreamReadSTRING(self, &map->mName);
  8.1259 +    _ctmStreamReadSTRING(self, &map->mFileName);
  8.1260 +    map->mPrecision = _ctmStreamReadFLOAT(self);
  8.1261 +    if(map->mPrecision <= 0.0f)
  8.1262 +    {
  8.1263 +      self->mError = CTM_BAD_FORMAT;
  8.1264 +      free((void *) intUVCoords);
  8.1265 +      return CTM_FALSE;
  8.1266 +    }
  8.1267 +    if(!_ctmStreamReadPackedInts(self, intUVCoords, self->mVertexCount, 2, CTM_TRUE))
  8.1268 +    {
  8.1269 +      free((void *) intUVCoords);
  8.1270 +      return CTM_FALSE;
  8.1271 +    }
  8.1272 +
  8.1273 +    // Restore UV coordinates
  8.1274 +    _ctmRestoreUVCoords(self, map, intUVCoords);
  8.1275 +
  8.1276 +    // Free temporary UV coordinate data
  8.1277 +    free((void *) intUVCoords);
  8.1278 +
  8.1279 +    map = map->mNext;
  8.1280 +  }
  8.1281 +
  8.1282 +  // Read vertex attribute maps
  8.1283 +  map = self->mAttribMaps;
  8.1284 +  while(map)
  8.1285 +  {
  8.1286 +    intAttribs = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 4);
  8.1287 +    if(!intAttribs)
  8.1288 +    {
  8.1289 +      self->mError = CTM_OUT_OF_MEMORY;
  8.1290 +      return CTM_FALSE;
  8.1291 +    }
  8.1292 +    if(_ctmStreamReadUINT(self) != FOURCC("ATTR"))
  8.1293 +    {
  8.1294 +      self->mError = CTM_BAD_FORMAT;
  8.1295 +      free((void *) intAttribs);
  8.1296 +      return CTM_FALSE;
  8.1297 +    }
  8.1298 +    _ctmStreamReadSTRING(self, &map->mName);
  8.1299 +    map->mPrecision = _ctmStreamReadFLOAT(self);
  8.1300 +    if(map->mPrecision <= 0.0f)
  8.1301 +    {
  8.1302 +      self->mError = CTM_BAD_FORMAT;
  8.1303 +      free((void *) intAttribs);
  8.1304 +      return CTM_FALSE;
  8.1305 +    }
  8.1306 +    if(!_ctmStreamReadPackedInts(self, intAttribs, self->mVertexCount, 4, CTM_TRUE))
  8.1307 +    {
  8.1308 +      free((void *) intAttribs);
  8.1309 +      return CTM_FALSE;
  8.1310 +    }
  8.1311 +
  8.1312 +    // Restore vertex attributes
  8.1313 +    _ctmRestoreAttribs(self, map, intAttribs);
  8.1314 +
  8.1315 +    // Free temporary vertex attribute data
  8.1316 +    free((void *) intAttribs);
  8.1317 +
  8.1318 +    map = map->mNext;
  8.1319 +  }
  8.1320 +
  8.1321 +  return CTM_TRUE;
  8.1322 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/libs/openctm/compressRAW.c	Thu Sep 26 04:47:05 2013 +0300
     9.3 @@ -0,0 +1,181 @@
     9.4 +//-----------------------------------------------------------------------------
     9.5 +// Product:     OpenCTM
     9.6 +// File:        compressRAW.c
     9.7 +// Description: Implementation of the RAW compression method.
     9.8 +//-----------------------------------------------------------------------------
     9.9 +// Copyright (c) 2009-2010 Marcus Geelnard
    9.10 +//
    9.11 +// This software is provided 'as-is', without any express or implied
    9.12 +// warranty. In no event will the authors be held liable for any damages
    9.13 +// arising from the use of this software.
    9.14 +//
    9.15 +// Permission is granted to anyone to use this software for any purpose,
    9.16 +// including commercial applications, and to alter it and redistribute it
    9.17 +// freely, subject to the following restrictions:
    9.18 +//
    9.19 +//     1. The origin of this software must not be misrepresented; you must not
    9.20 +//     claim that you wrote the original software. If you use this software
    9.21 +//     in a product, an acknowledgment in the product documentation would be
    9.22 +//     appreciated but is not required.
    9.23 +//
    9.24 +//     2. Altered source versions must be plainly marked as such, and must not
    9.25 +//     be misrepresented as being the original software.
    9.26 +//
    9.27 +//     3. This notice may not be removed or altered from any source
    9.28 +//     distribution.
    9.29 +//-----------------------------------------------------------------------------
    9.30 +
    9.31 +#include "openctm.h"
    9.32 +#include "internal.h"
    9.33 +
    9.34 +#ifdef __DEBUG_
    9.35 +#include <stdio.h>
    9.36 +#endif
    9.37 +
    9.38 +
    9.39 +//-----------------------------------------------------------------------------
    9.40 +// _ctmCompressMesh_RAW() - Compress the mesh that is stored in the CTM
    9.41 +// context using the RAW method, and write it the the output stream in the CTM
    9.42 +// context.
    9.43 +//-----------------------------------------------------------------------------
    9.44 +int _ctmCompressMesh_RAW(_CTMcontext * self)
    9.45 +{
    9.46 +  CTMuint i;
    9.47 +  _CTMfloatmap * map;
    9.48 +
    9.49 +#ifdef __DEBUG_
    9.50 +  printf("COMPRESSION METHOD: RAW\n");
    9.51 +#endif
    9.52 +
    9.53 +  // Write triangle indices
    9.54 +#ifdef __DEBUG_
    9.55 +  printf("Inidices: %d bytes\n", (CTMuint)(self->mTriangleCount * 3 * sizeof(CTMuint)));
    9.56 +#endif
    9.57 +  _ctmStreamWrite(self, (void *) "INDX", 4);
    9.58 +  for(i = 0; i < self->mTriangleCount * 3; ++ i)
    9.59 +    _ctmStreamWriteUINT(self, self->mIndices[i]);
    9.60 +
    9.61 +  // Write vertices
    9.62 +#ifdef __DEBUG_
    9.63 +  printf("Vertices: %d bytes\n", (CTMuint)(self->mVertexCount * 3 * sizeof(CTMfloat)));
    9.64 +#endif
    9.65 +  _ctmStreamWrite(self, (void *) "VERT", 4);
    9.66 +  for(i = 0; i < self->mVertexCount * 3; ++ i)
    9.67 +    _ctmStreamWriteFLOAT(self, self->mVertices[i]);
    9.68 +
    9.69 +  // Write normals
    9.70 +  if(self->mNormals)
    9.71 +  {
    9.72 +#ifdef __DEBUG_
    9.73 +    printf("Normals: %d bytes\n", (CTMuint)(self->mVertexCount * 3 * sizeof(CTMfloat)));
    9.74 +#endif
    9.75 +    _ctmStreamWrite(self, (void *) "NORM", 4);
    9.76 +    for(i = 0; i < self->mVertexCount * 3; ++ i)
    9.77 +      _ctmStreamWriteFLOAT(self, self->mNormals[i]);
    9.78 +  }
    9.79 +
    9.80 +  // Write UV maps
    9.81 +  map = self->mUVMaps;
    9.82 +  while(map)
    9.83 +  {
    9.84 +#ifdef __DEBUG_
    9.85 +    printf("UV coordinates (%s): %d bytes\n", map->mName ? map->mName : "no name", (CTMuint)(self->mVertexCount * 2 * sizeof(CTMfloat)));
    9.86 +#endif
    9.87 +    _ctmStreamWrite(self, (void *) "TEXC", 4);
    9.88 +    _ctmStreamWriteSTRING(self, map->mName);
    9.89 +    _ctmStreamWriteSTRING(self, map->mFileName);
    9.90 +    for(i = 0; i < self->mVertexCount * 2; ++ i)
    9.91 +      _ctmStreamWriteFLOAT(self, map->mValues[i]);
    9.92 +    map = map->mNext;
    9.93 +  }
    9.94 +
    9.95 +  // Write attribute maps
    9.96 +  map = self->mAttribMaps;
    9.97 +  while(map)
    9.98 +  {
    9.99 +#ifdef __DEBUG_
   9.100 +    printf("Vertex attributes (%s): %d bytes\n", map->mName ? map->mName : "no name", (CTMuint)(self->mVertexCount * 4 * sizeof(CTMfloat)));
   9.101 +#endif
   9.102 +    _ctmStreamWrite(self, (void *) "ATTR", 4);
   9.103 +    _ctmStreamWriteSTRING(self, map->mName);
   9.104 +    for(i = 0; i < self->mVertexCount * 4; ++ i)
   9.105 +      _ctmStreamWriteFLOAT(self, map->mValues[i]);
   9.106 +    map = map->mNext;
   9.107 +  }
   9.108 +
   9.109 +  return 1;
   9.110 +}
   9.111 +
   9.112 +//-----------------------------------------------------------------------------
   9.113 +// _ctmUncompressMesh_RAW() - Uncmpress the mesh from the input stream in the
   9.114 +// CTM context using the RAW method, and store the resulting mesh in the CTM
   9.115 +// context.
   9.116 +//-----------------------------------------------------------------------------
   9.117 +int _ctmUncompressMesh_RAW(_CTMcontext * self)
   9.118 +{
   9.119 +  CTMuint i;
   9.120 +  _CTMfloatmap * map;
   9.121 +
   9.122 +  // Read triangle indices
   9.123 +  if(_ctmStreamReadUINT(self) != FOURCC("INDX"))
   9.124 +  {
   9.125 +    self->mError = CTM_BAD_FORMAT;
   9.126 +    return 0;
   9.127 +  }
   9.128 +  for(i = 0; i < self->mTriangleCount * 3; ++ i)
   9.129 +    self->mIndices[i] = _ctmStreamReadUINT(self);
   9.130 +
   9.131 +  // Read vertices
   9.132 +  if(_ctmStreamReadUINT(self) != FOURCC("VERT"))
   9.133 +  {
   9.134 +    self->mError = CTM_BAD_FORMAT;
   9.135 +    return 0;
   9.136 +  }
   9.137 +  for(i = 0; i < self->mVertexCount * 3; ++ i)
   9.138 +    self->mVertices[i] = _ctmStreamReadFLOAT(self);
   9.139 +
   9.140 +  // Read normals
   9.141 +  if(self->mNormals)
   9.142 +  {
   9.143 +    if(_ctmStreamReadUINT(self) != FOURCC("NORM"))
   9.144 +    {
   9.145 +      self->mError = CTM_BAD_FORMAT;
   9.146 +      return 0;
   9.147 +    }
   9.148 +    for(i = 0; i < self->mVertexCount * 3; ++ i)
   9.149 +      self->mNormals[i] = _ctmStreamReadFLOAT(self);
   9.150 +  }
   9.151 +
   9.152 +  // Read UV maps
   9.153 +  map = self->mUVMaps;
   9.154 +  while(map)
   9.155 +  {
   9.156 +    if(_ctmStreamReadUINT(self) != FOURCC("TEXC"))
   9.157 +    {
   9.158 +      self->mError = CTM_BAD_FORMAT;
   9.159 +      return 0;
   9.160 +    }
   9.161 +    _ctmStreamReadSTRING(self, &map->mName);
   9.162 +    _ctmStreamReadSTRING(self, &map->mFileName);
   9.163 +    for(i = 0; i < self->mVertexCount * 2; ++ i)
   9.164 +      map->mValues[i] = _ctmStreamReadFLOAT(self);
   9.165 +    map = map->mNext;
   9.166 +  }
   9.167 +
   9.168 +  // Read attribute maps
   9.169 +  map = self->mAttribMaps;
   9.170 +  while(map)
   9.171 +  {
   9.172 +    if(_ctmStreamReadUINT(self) != FOURCC("ATTR"))
   9.173 +    {
   9.174 +      self->mError = CTM_BAD_FORMAT;
   9.175 +      return 0;
   9.176 +    }
   9.177 +    _ctmStreamReadSTRING(self, &map->mName);
   9.178 +    for(i = 0; i < self->mVertexCount * 4; ++ i)
   9.179 +      map->mValues[i] = _ctmStreamReadFLOAT(self);
   9.180 +    map = map->mNext;
   9.181 +  }
   9.182 +
   9.183 +  return 1;
   9.184 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/libs/openctm/internal.h	Thu Sep 26 04:47:05 2013 +0300
    10.3 @@ -0,0 +1,147 @@
    10.4 +//-----------------------------------------------------------------------------
    10.5 +// Product:     OpenCTM
    10.6 +// File:        internal.h
    10.7 +// Description: Internal (private) declarations, types and function prototypes.
    10.8 +//-----------------------------------------------------------------------------
    10.9 +// Copyright (c) 2009-2010 Marcus Geelnard
   10.10 +//
   10.11 +// This software is provided 'as-is', without any express or implied
   10.12 +// warranty. In no event will the authors be held liable for any damages
   10.13 +// arising from the use of this software.
   10.14 +//
   10.15 +// Permission is granted to anyone to use this software for any purpose,
   10.16 +// including commercial applications, and to alter it and redistribute it
   10.17 +// freely, subject to the following restrictions:
   10.18 +//
   10.19 +//     1. The origin of this software must not be misrepresented; you must not
   10.20 +//     claim that you wrote the original software. If you use this software
   10.21 +//     in a product, an acknowledgment in the product documentation would be
   10.22 +//     appreciated but is not required.
   10.23 +//
   10.24 +//     2. Altered source versions must be plainly marked as such, and must not
   10.25 +//     be misrepresented as being the original software.
   10.26 +//
   10.27 +//     3. This notice may not be removed or altered from any source
   10.28 +//     distribution.
   10.29 +//-----------------------------------------------------------------------------
   10.30 +
   10.31 +#ifndef __OPENCTM_INTERNAL_H_
   10.32 +#define __OPENCTM_INTERNAL_H_
   10.33 +
   10.34 +//-----------------------------------------------------------------------------
   10.35 +// Constants
   10.36 +//-----------------------------------------------------------------------------
   10.37 +// OpenCTM file format version (v5).
   10.38 +#define _CTM_FORMAT_VERSION  0x00000005
   10.39 +
   10.40 +// Flags for the Mesh flags field of the file header
   10.41 +#define _CTM_HAS_NORMALS_BIT 0x00000001
   10.42 +
   10.43 +//-----------------------------------------------------------------------------
   10.44 +// _CTMfloatmap - Internal representation of a floating point based vertex map
   10.45 +// (used for UV maps and attribute maps).
   10.46 +//-----------------------------------------------------------------------------
   10.47 +typedef struct _CTMfloatmap_struct _CTMfloatmap;
   10.48 +struct _CTMfloatmap_struct {
   10.49 +  char * mName;         // Unique name
   10.50 +  char * mFileName;     // File name reference (used only for UV maps)
   10.51 +  CTMfloat mPrecision;  // Precision for this map
   10.52 +  CTMfloat * mValues;   // Attribute/UV coordinate values (per vertex)
   10.53 +  _CTMfloatmap * mNext; // Pointer to the next map in the list (linked list)
   10.54 +};
   10.55 +
   10.56 +//-----------------------------------------------------------------------------
   10.57 +// _CTMcontext - Internal CTM context structure.
   10.58 +//-----------------------------------------------------------------------------
   10.59 +typedef struct {
   10.60 +  // Context mode (import or export)
   10.61 +  CTMenum mMode;
   10.62 +
   10.63 +  // Vertices
   10.64 +  CTMfloat * mVertices;
   10.65 +  CTMuint mVertexCount;
   10.66 +
   10.67 +  // Indices
   10.68 +  CTMuint * mIndices;
   10.69 +  CTMuint mTriangleCount;
   10.70 +
   10.71 +  // Normals (optional)
   10.72 +  CTMfloat * mNormals;
   10.73 +
   10.74 +  // Multiple sets of UV coordinate maps (optional)
   10.75 +  CTMuint mUVMapCount;
   10.76 +  _CTMfloatmap * mUVMaps;
   10.77 +
   10.78 +  // Multiple sets of custom vertex attribute maps (optional)
   10.79 +  CTMuint mAttribMapCount;
   10.80 +  _CTMfloatmap * mAttribMaps;
   10.81 +
   10.82 +  // Last error code
   10.83 +  CTMenum mError;
   10.84 +
   10.85 +  // The selected compression method
   10.86 +  CTMenum mMethod;
   10.87 +
   10.88 +  // The selected compression level
   10.89 +  CTMuint mCompressionLevel;
   10.90 +
   10.91 +  // Vertex coordinate precision
   10.92 +  CTMfloat mVertexPrecision;
   10.93 +
   10.94 +  // Normal precision (angular + magnitude)
   10.95 +  CTMfloat mNormalPrecision;
   10.96 +
   10.97 +  // File comment
   10.98 +  char * mFileComment;
   10.99 +
  10.100 +  // Read() function pointer
  10.101 +  CTMreadfn mReadFn;
  10.102 +
  10.103 +  // Write() function pointer
  10.104 +  CTMwritefn mWriteFn;
  10.105 +
  10.106 +  // User data (for stream read/write - usually the stream handle)
  10.107 +  void * mUserData;
  10.108 +} _CTMcontext;
  10.109 +
  10.110 +//-----------------------------------------------------------------------------
  10.111 +// Macros
  10.112 +//-----------------------------------------------------------------------------
  10.113 +#define FOURCC(str) (((CTMuint) str[0]) | (((CTMuint) str[1]) << 8) | \
  10.114 +                    (((CTMuint) str[2]) << 16) | (((CTMuint) str[3]) << 24))
  10.115 +
  10.116 +//-----------------------------------------------------------------------------
  10.117 +// Funcion prototypes for stream.c
  10.118 +//-----------------------------------------------------------------------------
  10.119 +CTMuint _ctmStreamRead(_CTMcontext * self, void * aBuf, CTMuint aCount);
  10.120 +CTMuint _ctmStreamWrite(_CTMcontext * self, void * aBuf, CTMuint aCount);
  10.121 +CTMuint _ctmStreamReadUINT(_CTMcontext * self);
  10.122 +void _ctmStreamWriteUINT(_CTMcontext * self, CTMuint aValue);
  10.123 +CTMfloat _ctmStreamReadFLOAT(_CTMcontext * self);
  10.124 +void _ctmStreamWriteFLOAT(_CTMcontext * self, CTMfloat aValue);
  10.125 +void _ctmStreamReadSTRING(_CTMcontext * self, char ** aValue);
  10.126 +void _ctmStreamWriteSTRING(_CTMcontext * self, const char * aValue);
  10.127 +int _ctmStreamReadPackedInts(_CTMcontext * self, CTMint * aData, CTMuint aCount, CTMuint aSize, CTMint aSignedInts);
  10.128 +int _ctmStreamWritePackedInts(_CTMcontext * self, CTMint * aData, CTMuint aCount, CTMuint aSize, CTMint aSignedInts);
  10.129 +int _ctmStreamReadPackedFloats(_CTMcontext * self, CTMfloat * aData, CTMuint aCount, CTMuint aSize);
  10.130 +int _ctmStreamWritePackedFloats(_CTMcontext * self, CTMfloat * aData, CTMuint aCount, CTMuint aSize);
  10.131 +
  10.132 +//-----------------------------------------------------------------------------
  10.133 +// Funcion prototypes for compressRAW.c
  10.134 +//-----------------------------------------------------------------------------
  10.135 +int _ctmCompressMesh_RAW(_CTMcontext * self);
  10.136 +int _ctmUncompressMesh_RAW(_CTMcontext * self);
  10.137 +
  10.138 +//-----------------------------------------------------------------------------
  10.139 +// Funcion prototypes for compressMG1.c
  10.140 +//-----------------------------------------------------------------------------
  10.141 +int _ctmCompressMesh_MG1(_CTMcontext * self);
  10.142 +int _ctmUncompressMesh_MG1(_CTMcontext * self);
  10.143 +
  10.144 +//-----------------------------------------------------------------------------
  10.145 +// Funcion prototypes for compressMG2.c
  10.146 +//-----------------------------------------------------------------------------
  10.147 +int _ctmCompressMesh_MG2(_CTMcontext * self);
  10.148 +int _ctmUncompressMesh_MG2(_CTMcontext * self);
  10.149 +
  10.150 +#endif // __OPENCTM_INTERNAL_H_
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/libs/openctm/liblzma/Alloc.c	Thu Sep 26 04:47:05 2013 +0300
    11.3 @@ -0,0 +1,127 @@
    11.4 +/* Alloc.c -- Memory allocation functions
    11.5 +2008-09-24
    11.6 +Igor Pavlov
    11.7 +Public domain */
    11.8 +
    11.9 +#ifdef _WIN32
   11.10 +#include <windows.h>
   11.11 +#endif
   11.12 +#include <stdlib.h>
   11.13 +
   11.14 +#include "Alloc.h"
   11.15 +
   11.16 +/* #define _SZ_ALLOC_DEBUG */
   11.17 +
   11.18 +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
   11.19 +#ifdef _SZ_ALLOC_DEBUG
   11.20 +#include <stdio.h>
   11.21 +int g_allocCount = 0;
   11.22 +int g_allocCountMid = 0;
   11.23 +int g_allocCountBig = 0;
   11.24 +#endif
   11.25 +
   11.26 +void *MyAlloc(size_t size)
   11.27 +{
   11.28 +  if (size == 0)
   11.29 +    return 0;
   11.30 +  #ifdef _SZ_ALLOC_DEBUG
   11.31 +  {
   11.32 +    void *p = malloc(size);
   11.33 +    fprintf(stderr, "\nAlloc %10d bytes, count = %10d,  addr = %8X", size, g_allocCount++, (unsigned)p);
   11.34 +    return p;
   11.35 +  }
   11.36 +  #else
   11.37 +  return malloc(size);
   11.38 +  #endif
   11.39 +}
   11.40 +
   11.41 +void MyFree(void *address)
   11.42 +{
   11.43 +  #ifdef _SZ_ALLOC_DEBUG
   11.44 +  if (address != 0)
   11.45 +    fprintf(stderr, "\nFree; count = %10d,  addr = %8X", --g_allocCount, (unsigned)address);
   11.46 +  #endif
   11.47 +  free(address);
   11.48 +}
   11.49 +
   11.50 +#ifdef _WIN32
   11.51 +
   11.52 +void *MidAlloc(size_t size)
   11.53 +{
   11.54 +  if (size == 0)
   11.55 +    return 0;
   11.56 +  #ifdef _SZ_ALLOC_DEBUG
   11.57 +  fprintf(stderr, "\nAlloc_Mid %10d bytes;  count = %10d", size, g_allocCountMid++);
   11.58 +  #endif
   11.59 +  return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
   11.60 +}
   11.61 +
   11.62 +void MidFree(void *address)
   11.63 +{
   11.64 +  #ifdef _SZ_ALLOC_DEBUG
   11.65 +  if (address != 0)
   11.66 +    fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);
   11.67 +  #endif
   11.68 +  if (address == 0)
   11.69 +    return;
   11.70 +  VirtualFree(address, 0, MEM_RELEASE);
   11.71 +}
   11.72 +
   11.73 +#ifndef MEM_LARGE_PAGES
   11.74 +#undef _7ZIP_LARGE_PAGES
   11.75 +#endif
   11.76 +
   11.77 +#ifdef _7ZIP_LARGE_PAGES
   11.78 +SIZE_T g_LargePageSize = 0;
   11.79 +typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
   11.80 +#endif
   11.81 +
   11.82 +void SetLargePageSize()
   11.83 +{
   11.84 +  #ifdef _7ZIP_LARGE_PAGES
   11.85 +  SIZE_T size = 0;
   11.86 +  GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
   11.87 +        GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
   11.88 +  if (largePageMinimum == 0)
   11.89 +    return;
   11.90 +  size = largePageMinimum();
   11.91 +  if (size == 0 || (size & (size - 1)) != 0)
   11.92 +    return;
   11.93 +  g_LargePageSize = size;
   11.94 +  #endif
   11.95 +}
   11.96 +
   11.97 +
   11.98 +void *BigAlloc(size_t size)
   11.99 +{
  11.100 +  if (size == 0)
  11.101 +    return 0;
  11.102 +  #ifdef _SZ_ALLOC_DEBUG
  11.103 +  fprintf(stderr, "\nAlloc_Big %10d bytes;  count = %10d", size, g_allocCountBig++);
  11.104 +  #endif
  11.105 +  
  11.106 +  #ifdef _7ZIP_LARGE_PAGES
  11.107 +  if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))
  11.108 +  {
  11.109 +    void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
  11.110 +        MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
  11.111 +    if (res != 0)
  11.112 +      return res;
  11.113 +  }
  11.114 +  #endif
  11.115 +  return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
  11.116 +}
  11.117 +
  11.118 +void BigFree(void *address)
  11.119 +{
  11.120 +  #ifdef _SZ_ALLOC_DEBUG
  11.121 +  if (address != 0)
  11.122 +    fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
  11.123 +  #endif
  11.124 +  
  11.125 +  if (address == 0)
  11.126 +    return;
  11.127 +  VirtualFree(address, 0, MEM_RELEASE);
  11.128 +}
  11.129 +
  11.130 +#endif
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/libs/openctm/liblzma/Alloc.h	Thu Sep 26 04:47:05 2013 +0300
    12.3 @@ -0,0 +1,34 @@
    12.4 +/* Alloc.h -- Memory allocation functions
    12.5 +2008-03-13
    12.6 +Igor Pavlov
    12.7 +Public domain */
    12.8 +
    12.9 +#ifndef __COMMON_ALLOC_H
   12.10 +#define __COMMON_ALLOC_H
   12.11 +
   12.12 +#include <stddef.h>
   12.13 +
   12.14 +#include "NameMangle.h"
   12.15 +
   12.16 +void *MyAlloc(size_t size);
   12.17 +void MyFree(void *address);
   12.18 +
   12.19 +#ifdef _WIN32
   12.20 +
   12.21 +void SetLargePageSize();
   12.22 +
   12.23 +void *MidAlloc(size_t size);
   12.24 +void MidFree(void *address);
   12.25 +void *BigAlloc(size_t size);
   12.26 +void BigFree(void *address);
   12.27 +
   12.28 +#else
   12.29 +
   12.30 +#define MidAlloc(size) MyAlloc(size)
   12.31 +#define MidFree(address) MyFree(address)
   12.32 +#define BigAlloc(size) MyAlloc(size)
   12.33 +#define BigFree(address) MyFree(address)
   12.34 +
   12.35 +#endif
   12.36 +
   12.37 +#endif
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/libs/openctm/liblzma/LzFind.c	Thu Sep 26 04:47:05 2013 +0300
    13.3 @@ -0,0 +1,751 @@
    13.4 +/* LzFind.c -- Match finder for LZ algorithms
    13.5 +2008-10-04 : Igor Pavlov : Public domain */
    13.6 +
    13.7 +#include <string.h>
    13.8 +
    13.9 +#include "LzFind.h"
   13.10 +#include "LzHash.h"
   13.11 +
   13.12 +#define kEmptyHashValue 0
   13.13 +#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
   13.14 +#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
   13.15 +#define kNormalizeMask (~(kNormalizeStepMin - 1))
   13.16 +#define kMaxHistorySize ((UInt32)3 << 30)
   13.17 +
   13.18 +#define kStartMaxLen 3
   13.19 +
   13.20 +static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
   13.21 +{
   13.22 +  if (!p->directInput)
   13.23 +  {
   13.24 +    alloc->Free(alloc, p->bufferBase);
   13.25 +    p->bufferBase = 0;
   13.26 +  }
   13.27 +}
   13.28 +
   13.29 +/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
   13.30 +
   13.31 +static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
   13.32 +{
   13.33 +  UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
   13.34 +  if (p->directInput)
   13.35 +  {
   13.36 +    p->blockSize = blockSize;
   13.37 +    return 1;
   13.38 +  }
   13.39 +  if (p->bufferBase == 0 || p->blockSize != blockSize)
   13.40 +  {
   13.41 +    LzInWindow_Free(p, alloc);
   13.42 +    p->blockSize = blockSize;
   13.43 +    p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
   13.44 +  }
   13.45 +  return (p->bufferBase != 0);
   13.46 +}
   13.47 +
   13.48 +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
   13.49 +Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
   13.50 +
   13.51 +UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
   13.52 +
   13.53 +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
   13.54 +{
   13.55 +  p->posLimit -= subValue;
   13.56 +  p->pos -= subValue;
   13.57 +  p->streamPos -= subValue;
   13.58 +}
   13.59 +
   13.60 +static void MatchFinder_ReadBlock(CMatchFinder *p)
   13.61 +{
   13.62 +  if (p->streamEndWasReached || p->result != SZ_OK)
   13.63 +    return;
   13.64 +  for (;;)
   13.65 +  {
   13.66 +    Byte *dest = p->buffer + (p->streamPos - p->pos);
   13.67 +    size_t size = (p->bufferBase + p->blockSize - dest);
   13.68 +    if (size == 0)
   13.69 +      return;
   13.70 +    p->result = p->stream->Read(p->stream, dest, &size);
   13.71 +    if (p->result != SZ_OK)
   13.72 +      return;
   13.73 +    if (size == 0)
   13.74 +    {
   13.75 +      p->streamEndWasReached = 1;
   13.76 +      return;
   13.77 +    }
   13.78 +    p->streamPos += (UInt32)size;
   13.79 +    if (p->streamPos - p->pos > p->keepSizeAfter)
   13.80 +      return;
   13.81 +  }
   13.82 +}
   13.83 +
   13.84 +void MatchFinder_MoveBlock(CMatchFinder *p)
   13.85 +{
   13.86 +  memmove(p->bufferBase,
   13.87 +    p->buffer - p->keepSizeBefore,
   13.88 +    (size_t)(p->streamPos - p->pos + p->keepSizeBefore));
   13.89 +  p->buffer = p->bufferBase + p->keepSizeBefore;
   13.90 +}
   13.91 +
   13.92 +int MatchFinder_NeedMove(CMatchFinder *p)
   13.93 +{
   13.94 +  /* if (p->streamEndWasReached) return 0; */
   13.95 +  return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
   13.96 +}
   13.97 +
   13.98 +void MatchFinder_ReadIfRequired(CMatchFinder *p)
   13.99 +{
  13.100 +  if (p->streamEndWasReached)
  13.101 +    return;
  13.102 +  if (p->keepSizeAfter >= p->streamPos - p->pos)
  13.103 +    MatchFinder_ReadBlock(p);
  13.104 +}
  13.105 +
  13.106 +static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
  13.107 +{
  13.108 +  if (MatchFinder_NeedMove(p))
  13.109 +    MatchFinder_MoveBlock(p);
  13.110 +  MatchFinder_ReadBlock(p);
  13.111 +}
  13.112 +
  13.113 +static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
  13.114 +{
  13.115 +  p->cutValue = 32;
  13.116 +  p->btMode = 1;
  13.117 +  p->numHashBytes = 4;
  13.118 +  /* p->skipModeBits = 0; */
  13.119 +  p->directInput = 0;
  13.120 +  p->bigHash = 0;
  13.121 +}
  13.122 +
  13.123 +#define kCrcPoly 0xEDB88320
  13.124 +
  13.125 +void MatchFinder_Construct(CMatchFinder *p)
  13.126 +{
  13.127 +  UInt32 i;
  13.128 +  p->bufferBase = 0;
  13.129 +  p->directInput = 0;
  13.130 +  p->hash = 0;
  13.131 +  MatchFinder_SetDefaultSettings(p);
  13.132 +
  13.133 +  for (i = 0; i < 256; i++)
  13.134 +  {
  13.135 +    UInt32 r = i;
  13.136 +    int j;
  13.137 +    for (j = 0; j < 8; j++)
  13.138 +      r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
  13.139 +    p->crc[i] = r;
  13.140 +  }
  13.141 +}
  13.142 +
  13.143 +static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
  13.144 +{
  13.145 +  alloc->Free(alloc, p->hash);
  13.146 +  p->hash = 0;
  13.147 +}
  13.148 +
  13.149 +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
  13.150 +{
  13.151 +  MatchFinder_FreeThisClassMemory(p, alloc);
  13.152 +  LzInWindow_Free(p, alloc);
  13.153 +}
  13.154 +
  13.155 +static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
  13.156 +{
  13.157 +  size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
  13.158 +  if (sizeInBytes / sizeof(CLzRef) != num)
  13.159 +    return 0;
  13.160 +  return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
  13.161 +}
  13.162 +
  13.163 +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
  13.164 +    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
  13.165 +    ISzAlloc *alloc)
  13.166 +{
  13.167 +  UInt32 sizeReserv;
  13.168 +  if (historySize > kMaxHistorySize)
  13.169 +  {
  13.170 +    MatchFinder_Free(p, alloc);
  13.171 +    return 0;
  13.172 +  }
  13.173 +  sizeReserv = historySize >> 1;
  13.174 +  if (historySize > ((UInt32)2 << 30))
  13.175 +    sizeReserv = historySize >> 2;
  13.176 +  sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
  13.177 +
  13.178 +  p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
  13.179 +  p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
  13.180 +  /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
  13.181 +  if (LzInWindow_Create(p, sizeReserv, alloc))
  13.182 +  {
  13.183 +    UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1;
  13.184 +    UInt32 hs;
  13.185 +    p->matchMaxLen = matchMaxLen;
  13.186 +    {
  13.187 +      p->fixedHashSize = 0;
  13.188 +      if (p->numHashBytes == 2)
  13.189 +        hs = (1 << 16) - 1;
  13.190 +      else
  13.191 +      {
  13.192 +        hs = historySize - 1;
  13.193 +        hs |= (hs >> 1);
  13.194 +        hs |= (hs >> 2);
  13.195 +        hs |= (hs >> 4);
  13.196 +        hs |= (hs >> 8);
  13.197 +        hs >>= 1;
  13.198 +        /* hs >>= p->skipModeBits; */
  13.199 +        hs |= 0xFFFF; /* don't change it! It's required for Deflate */
  13.200 +        if (hs > (1 << 24))
  13.201 +        {
  13.202 +          if (p->numHashBytes == 3)
  13.203 +            hs = (1 << 24) - 1;
  13.204 +          else
  13.205 +            hs >>= 1;
  13.206 +        }
  13.207 +      }
  13.208 +      p->hashMask = hs;
  13.209 +      hs++;
  13.210 +      if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
  13.211 +      if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
  13.212 +      if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
  13.213 +      hs += p->fixedHashSize;
  13.214 +    }
  13.215 +
  13.216 +    {
  13.217 +      UInt32 prevSize = p->hashSizeSum + p->numSons;
  13.218 +      UInt32 newSize;
  13.219 +      p->historySize = historySize;
  13.220 +      p->hashSizeSum = hs;
  13.221 +      p->cyclicBufferSize = newCyclicBufferSize;
  13.222 +      p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
  13.223 +      newSize = p->hashSizeSum + p->numSons;
  13.224 +      if (p->hash != 0 && prevSize == newSize)
  13.225 +        return 1;
  13.226 +      MatchFinder_FreeThisClassMemory(p, alloc);
  13.227 +      p->hash = AllocRefs(newSize, alloc);
  13.228 +      if (p->hash != 0)
  13.229 +      {
  13.230 +        p->son = p->hash + p->hashSizeSum;
  13.231 +        return 1;
  13.232 +      }
  13.233 +    }
  13.234 +  }
  13.235 +  MatchFinder_Free(p, alloc);
  13.236 +  return 0;
  13.237 +}
  13.238 +
  13.239 +static void MatchFinder_SetLimits(CMatchFinder *p)
  13.240 +{
  13.241 +  UInt32 limit = kMaxValForNormalize - p->pos;
  13.242 +  UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
  13.243 +  if (limit2 < limit)
  13.244 +    limit = limit2;
  13.245 +  limit2 = p->streamPos - p->pos;
  13.246 +  if (limit2 <= p->keepSizeAfter)
  13.247 +  {
  13.248 +    if (limit2 > 0)
  13.249 +      limit2 = 1;
  13.250 +  }
  13.251 +  else
  13.252 +    limit2 -= p->keepSizeAfter;
  13.253 +  if (limit2 < limit)
  13.254 +    limit = limit2;
  13.255 +  {
  13.256 +    UInt32 lenLimit = p->streamPos - p->pos;
  13.257 +    if (lenLimit > p->matchMaxLen)
  13.258 +      lenLimit = p->matchMaxLen;
  13.259 +    p->lenLimit = lenLimit;
  13.260 +  }
  13.261 +  p->posLimit = p->pos + limit;
  13.262 +}
  13.263 +
  13.264 +void MatchFinder_Init(CMatchFinder *p)
  13.265 +{
  13.266 +  UInt32 i;
  13.267 +  for (i = 0; i < p->hashSizeSum; i++)
  13.268 +    p->hash[i] = kEmptyHashValue;
  13.269 +  p->cyclicBufferPos = 0;
  13.270 +  p->buffer = p->bufferBase;
  13.271 +  p->pos = p->streamPos = p->cyclicBufferSize;
  13.272 +  p->result = SZ_OK;
  13.273 +  p->streamEndWasReached = 0;
  13.274 +  MatchFinder_ReadBlock(p);
  13.275 +  MatchFinder_SetLimits(p);
  13.276 +}
  13.277 +
  13.278 +static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
  13.279 +{
  13.280 +  return (p->pos - p->historySize - 1) & kNormalizeMask;
  13.281 +}
  13.282 +
  13.283 +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
  13.284 +{
  13.285 +  UInt32 i;
  13.286 +  for (i = 0; i < numItems; i++)
  13.287 +  {
  13.288 +    UInt32 value = items[i];
  13.289 +    if (value <= subValue)
  13.290 +      value = kEmptyHashValue;
  13.291 +    else
  13.292 +      value -= subValue;
  13.293 +    items[i] = value;
  13.294 +  }
  13.295 +}
  13.296 +
  13.297 +static void MatchFinder_Normalize(CMatchFinder *p)
  13.298 +{
  13.299 +  UInt32 subValue = MatchFinder_GetSubValue(p);
  13.300 +  MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
  13.301 +  MatchFinder_ReduceOffsets(p, subValue);
  13.302 +}
  13.303 +
  13.304 +static void MatchFinder_CheckLimits(CMatchFinder *p)
  13.305 +{
  13.306 +  if (p->pos == kMaxValForNormalize)
  13.307 +    MatchFinder_Normalize(p);
  13.308 +  if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
  13.309 +    MatchFinder_CheckAndMoveAndRead(p);
  13.310 +  if (p->cyclicBufferPos == p->cyclicBufferSize)
  13.311 +    p->cyclicBufferPos = 0;
  13.312 +  MatchFinder_SetLimits(p);
  13.313 +}
  13.314 +
  13.315 +static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
  13.316 +    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
  13.317 +    UInt32 *distances, UInt32 maxLen)
  13.318 +{
  13.319 +  son[_cyclicBufferPos] = curMatch;
  13.320 +  for (;;)
  13.321 +  {
  13.322 +    UInt32 delta = pos - curMatch;
  13.323 +    if (cutValue-- == 0 || delta >= _cyclicBufferSize)
  13.324 +      return distances;
  13.325 +    {
  13.326 +      const Byte *pb = cur - delta;
  13.327 +      curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
  13.328 +      if (pb[maxLen] == cur[maxLen] && *pb == *cur)
  13.329 +      {
  13.330 +        UInt32 len = 0;
  13.331 +        while (++len != lenLimit)
  13.332 +          if (pb[len] != cur[len])
  13.333 +            break;
  13.334 +        if (maxLen < len)
  13.335 +        {
  13.336 +          *distances++ = maxLen = len;
  13.337 +          *distances++ = delta - 1;
  13.338 +          if (len == lenLimit)
  13.339 +            return distances;
  13.340 +        }
  13.341 +      }
  13.342 +    }
  13.343 +  }
  13.344 +}
  13.345 +
  13.346 +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
  13.347 +    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
  13.348 +    UInt32 *distances, UInt32 maxLen)
  13.349 +{
  13.350 +  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
  13.351 +  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
  13.352 +  UInt32 len0 = 0, len1 = 0;
  13.353 +  for (;;)
  13.354 +  {
  13.355 +    UInt32 delta = pos - curMatch;
  13.356 +    if (cutValue-- == 0 || delta >= _cyclicBufferSize)
  13.357 +    {
  13.358 +      *ptr0 = *ptr1 = kEmptyHashValue;
  13.359 +      return distances;
  13.360 +    }
  13.361 +    {
  13.362 +      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
  13.363 +      const Byte *pb = cur - delta;
  13.364 +      UInt32 len = (len0 < len1 ? len0 : len1);
  13.365 +      if (pb[len] == cur[len])
  13.366 +      {
  13.367 +        if (++len != lenLimit && pb[len] == cur[len])
  13.368 +          while (++len != lenLimit)
  13.369 +            if (pb[len] != cur[len])
  13.370 +              break;
  13.371 +        if (maxLen < len)
  13.372 +        {
  13.373 +          *distances++ = maxLen = len;
  13.374 +          *distances++ = delta - 1;
  13.375 +          if (len == lenLimit)
  13.376 +          {
  13.377 +            *ptr1 = pair[0];
  13.378 +            *ptr0 = pair[1];
  13.379 +            return distances;
  13.380 +          }
  13.381 +        }
  13.382 +      }
  13.383 +      if (pb[len] < cur[len])
  13.384 +      {
  13.385 +        *ptr1 = curMatch;
  13.386 +        ptr1 = pair + 1;
  13.387 +        curMatch = *ptr1;
  13.388 +        len1 = len;
  13.389 +      }
  13.390 +      else
  13.391 +      {
  13.392 +        *ptr0 = curMatch;
  13.393 +        ptr0 = pair;
  13.394 +        curMatch = *ptr0;
  13.395 +        len0 = len;
  13.396 +      }
  13.397 +    }
  13.398 +  }
  13.399 +}
  13.400 +
  13.401 +static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
  13.402 +    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
  13.403 +{
  13.404 +  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
  13.405 +  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
  13.406 +  UInt32 len0 = 0, len1 = 0;
  13.407 +  for (;;)
  13.408 +  {
  13.409 +    UInt32 delta = pos - curMatch;
  13.410 +    if (cutValue-- == 0 || delta >= _cyclicBufferSize)
  13.411 +    {
  13.412 +      *ptr0 = *ptr1 = kEmptyHashValue;
  13.413 +      return;
  13.414 +    }
  13.415 +    {
  13.416 +      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
  13.417 +      const Byte *pb = cur - delta;
  13.418 +      UInt32 len = (len0 < len1 ? len0 : len1);
  13.419 +      if (pb[len] == cur[len])
  13.420 +      {
  13.421 +        while (++len != lenLimit)
  13.422 +          if (pb[len] != cur[len])
  13.423 +            break;
  13.424 +        {
  13.425 +          if (len == lenLimit)
  13.426 +          {
  13.427 +            *ptr1 = pair[0];
  13.428 +            *ptr0 = pair[1];
  13.429 +            return;
  13.430 +          }
  13.431 +        }
  13.432 +      }
  13.433 +      if (pb[len] < cur[len])
  13.434 +      {
  13.435 +        *ptr1 = curMatch;
  13.436 +        ptr1 = pair + 1;
  13.437 +        curMatch = *ptr1;
  13.438 +        len1 = len;
  13.439 +      }
  13.440 +      else
  13.441 +      {
  13.442 +        *ptr0 = curMatch;
  13.443 +        ptr0 = pair;
  13.444 +        curMatch = *ptr0;
  13.445 +        len0 = len;
  13.446 +      }
  13.447 +    }
  13.448 +  }
  13.449 +}
  13.450 +
  13.451 +#define MOVE_POS \
  13.452 +  ++p->cyclicBufferPos; \
  13.453 +  p->buffer++; \
  13.454 +  if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
  13.455 +
  13.456 +#define MOVE_POS_RET MOVE_POS return offset;
  13.457 +
  13.458 +static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
  13.459 +
  13.460 +#define GET_MATCHES_HEADER2(minLen, ret_op) \
  13.461 +  UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
  13.462 +  lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
  13.463 +  cur = p->buffer;
  13.464 +
  13.465 +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
  13.466 +#define SKIP_HEADER(minLen)        GET_MATCHES_HEADER2(minLen, continue)
  13.467 +
  13.468 +#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
  13.469 +
  13.470 +#define GET_MATCHES_FOOTER(offset, maxLen) \
  13.471 +  offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
  13.472 +  distances + offset, maxLen) - distances); MOVE_POS_RET;
  13.473 +
  13.474 +#define SKIP_FOOTER \
  13.475 +  SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
  13.476 +
  13.477 +static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  13.478 +{
  13.479 +  UInt32 offset;
  13.480 +  GET_MATCHES_HEADER(2)
  13.481 +  HASH2_CALC;
  13.482 +  curMatch = p->hash[hashValue];
  13.483 +  p->hash[hashValue] = p->pos;
  13.484 +  offset = 0;
  13.485 +  GET_MATCHES_FOOTER(offset, 1)
  13.486 +}
  13.487 +
  13.488 +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  13.489 +{
  13.490 +  UInt32 offset;
  13.491 +  GET_MATCHES_HEADER(3)
  13.492 +  HASH_ZIP_CALC;
  13.493 +  curMatch = p->hash[hashValue];
  13.494 +  p->hash[hashValue] = p->pos;
  13.495 +  offset = 0;
  13.496 +  GET_MATCHES_FOOTER(offset, 2)
  13.497 +}
  13.498 +
  13.499 +static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  13.500 +{
  13.501 +  UInt32 hash2Value, delta2, maxLen, offset;
  13.502 +  GET_MATCHES_HEADER(3)
  13.503 +
  13.504 +  HASH3_CALC;
  13.505 +
  13.506 +  delta2 = p->pos - p->hash[hash2Value];
  13.507 +  curMatch = p->hash[kFix3HashSize + hashValue];
  13.508 +  
  13.509 +  p->hash[hash2Value] =
  13.510 +  p->hash[kFix3HashSize + hashValue] = p->pos;
  13.511 +
  13.512 +
  13.513 +  maxLen = 2;
  13.514 +  offset = 0;
  13.515 +  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
  13.516 +  {
  13.517 +    for (; maxLen != lenLimit; maxLen++)
  13.518 +      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
  13.519 +        break;
  13.520 +    distances[0] = maxLen;
  13.521 +    distances[1] = delta2 - 1;
  13.522 +    offset = 2;
  13.523 +    if (maxLen == lenLimit)
  13.524 +    {
  13.525 +      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
  13.526 +      MOVE_POS_RET;
  13.527 +    }
  13.528 +  }
  13.529 +  GET_MATCHES_FOOTER(offset, maxLen)
  13.530 +}
  13.531 +
  13.532 +static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  13.533 +{
  13.534 +  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
  13.535 +  GET_MATCHES_HEADER(4)
  13.536 +
  13.537 +  HASH4_CALC;
  13.538 +
  13.539 +  delta2 = p->pos - p->hash[                hash2Value];
  13.540 +  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
  13.541 +  curMatch = p->hash[kFix4HashSize + hashValue];
  13.542 +  
  13.543 +  p->hash[                hash2Value] =
  13.544 +  p->hash[kFix3HashSize + hash3Value] =
  13.545 +  p->hash[kFix4HashSize + hashValue] = p->pos;
  13.546 +
  13.547 +  maxLen = 1;
  13.548 +  offset = 0;
  13.549 +  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
  13.550 +  {
  13.551 +    distances[0] = maxLen = 2;
  13.552 +    distances[1] = delta2 - 1;
  13.553 +    offset = 2;
  13.554 +  }
  13.555 +  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
  13.556 +  {
  13.557 +    maxLen = 3;
  13.558 +    distances[offset + 1] = delta3 - 1;
  13.559 +    offset += 2;
  13.560 +    delta2 = delta3;
  13.561 +  }
  13.562 +  if (offset != 0)
  13.563 +  {
  13.564 +    for (; maxLen != lenLimit; maxLen++)
  13.565 +      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
  13.566 +        break;
  13.567 +    distances[offset - 2] = maxLen;
  13.568 +    if (maxLen == lenLimit)
  13.569 +    {
  13.570 +      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
  13.571 +      MOVE_POS_RET;
  13.572 +    }
  13.573 +  }
  13.574 +  if (maxLen < 3)
  13.575 +    maxLen = 3;
  13.576 +  GET_MATCHES_FOOTER(offset, maxLen)
  13.577 +}
  13.578 +
  13.579 +static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  13.580 +{
  13.581 +  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
  13.582 +  GET_MATCHES_HEADER(4)
  13.583 +
  13.584 +  HASH4_CALC;
  13.585 +
  13.586 +  delta2 = p->pos - p->hash[                hash2Value];
  13.587 +  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
  13.588 +  curMatch = p->hash[kFix4HashSize + hashValue];
  13.589 +
  13.590 +  p->hash[                hash2Value] =
  13.591 +  p->hash[kFix3HashSize + hash3Value] =
  13.592 +  p->hash[kFix4HashSize + hashValue] = p->pos;
  13.593 +
  13.594 +  maxLen = 1;
  13.595 +  offset = 0;
  13.596 +  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
  13.597 +  {
  13.598 +    distances[0] = maxLen = 2;
  13.599 +    distances[1] = delta2 - 1;
  13.600 +    offset = 2;
  13.601 +  }
  13.602 +  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
  13.603 +  {
  13.604 +    maxLen = 3;
  13.605 +    distances[offset + 1] = delta3 - 1;
  13.606 +    offset += 2;
  13.607 +    delta2 = delta3;
  13.608 +  }
  13.609 +  if (offset != 0)
  13.610 +  {
  13.611 +    for (; maxLen != lenLimit; maxLen++)
  13.612 +      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
  13.613 +        break;
  13.614 +    distances[offset - 2] = maxLen;
  13.615 +    if (maxLen == lenLimit)
  13.616 +    {
  13.617 +      p->son[p->cyclicBufferPos] = curMatch;
  13.618 +      MOVE_POS_RET;
  13.619 +    }
  13.620 +  }
  13.621 +  if (maxLen < 3)
  13.622 +    maxLen = 3;
  13.623 +  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
  13.624 +    distances + offset, maxLen) - (distances));
  13.625 +  MOVE_POS_RET
  13.626 +}
  13.627 +
  13.628 +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
  13.629 +{
  13.630 +  UInt32 offset;
  13.631 +  GET_MATCHES_HEADER(3)
  13.632 +  HASH_ZIP_CALC;
  13.633 +  curMatch = p->hash[hashValue];
  13.634 +  p->hash[hashValue] = p->pos;
  13.635 +  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
  13.636 +    distances, 2) - (distances));
  13.637 +  MOVE_POS_RET
  13.638 +}
  13.639 +
  13.640 +static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  13.641 +{
  13.642 +  do
  13.643 +  {
  13.644 +    SKIP_HEADER(2)
  13.645 +    HASH2_CALC;
  13.646 +    curMatch = p->hash[hashValue];
  13.647 +    p->hash[hashValue] = p->pos;
  13.648 +    SKIP_FOOTER
  13.649 +  }
  13.650 +  while (--num != 0);
  13.651 +}
  13.652 +
  13.653 +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  13.654 +{
  13.655 +  do
  13.656 +  {
  13.657 +    SKIP_HEADER(3)
  13.658 +    HASH_ZIP_CALC;
  13.659 +    curMatch = p->hash[hashValue];
  13.660 +    p->hash[hashValue] = p->pos;
  13.661 +    SKIP_FOOTER
  13.662 +  }
  13.663 +  while (--num != 0);
  13.664 +}
  13.665 +
  13.666 +static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  13.667 +{
  13.668 +  do
  13.669 +  {
  13.670 +    UInt32 hash2Value;
  13.671 +    SKIP_HEADER(3)
  13.672 +    HASH3_CALC;
  13.673 +    curMatch = p->hash[kFix3HashSize + hashValue];
  13.674 +    p->hash[hash2Value] =
  13.675 +    p->hash[kFix3HashSize + hashValue] = p->pos;
  13.676 +    SKIP_FOOTER
  13.677 +  }
  13.678 +  while (--num != 0);
  13.679 +}
  13.680 +
  13.681 +static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  13.682 +{
  13.683 +  do
  13.684 +  {
  13.685 +    UInt32 hash2Value, hash3Value;
  13.686 +    SKIP_HEADER(4)
  13.687 +    HASH4_CALC;
  13.688 +    curMatch = p->hash[kFix4HashSize + hashValue];
  13.689 +    p->hash[                hash2Value] =
  13.690 +    p->hash[kFix3HashSize + hash3Value] = p->pos;
  13.691 +    p->hash[kFix4HashSize + hashValue] = p->pos;
  13.692 +    SKIP_FOOTER
  13.693 +  }
  13.694 +  while (--num != 0);
  13.695 +}
  13.696 +
  13.697 +static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  13.698 +{
  13.699 +  do
  13.700 +  {
  13.701 +    UInt32 hash2Value, hash3Value;
  13.702 +    SKIP_HEADER(4)
  13.703 +    HASH4_CALC;
  13.704 +    curMatch = p->hash[kFix4HashSize + hashValue];
  13.705 +    p->hash[                hash2Value] =
  13.706 +    p->hash[kFix3HashSize + hash3Value] =
  13.707 +    p->hash[kFix4HashSize + hashValue] = p->pos;
  13.708 +    p->son[p->cyclicBufferPos] = curMatch;
  13.709 +    MOVE_POS
  13.710 +  }
  13.711 +  while (--num != 0);
  13.712 +}
  13.713 +
  13.714 +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
  13.715 +{
  13.716 +  do
  13.717 +  {
  13.718 +    SKIP_HEADER(3)
  13.719 +    HASH_ZIP_CALC;
  13.720 +    curMatch = p->hash[hashValue];
  13.721 +    p->hash[hashValue] = p->pos;
  13.722 +    p->son[p->cyclicBufferPos] = curMatch;
  13.723 +    MOVE_POS
  13.724 +  }
  13.725 +  while (--num != 0);
  13.726 +}
  13.727 +
  13.728 +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
  13.729 +{
  13.730 +  vTable->Init = (Mf_Init_Func)MatchFinder_Init;
  13.731 +  vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
  13.732 +  vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
  13.733 +  vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
  13.734 +  if (!p->btMode)
  13.735 +  {
  13.736 +    vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
  13.737 +    vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
  13.738 +  }
  13.739 +  else if (p->numHashBytes == 2)
  13.740 +  {
  13.741 +    vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
  13.742 +    vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
  13.743 +  }
  13.744 +  else if (p->numHashBytes == 3)
  13.745 +  {
  13.746 +    vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
  13.747 +    vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
  13.748 +  }
  13.749 +  else
  13.750 +  {
  13.751 +    vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
  13.752 +    vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
  13.753 +  }
  13.754 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/libs/openctm/liblzma/LzFind.h	Thu Sep 26 04:47:05 2013 +0300
    14.3 @@ -0,0 +1,107 @@
    14.4 +/* LzFind.h -- Match finder for LZ algorithms
    14.5 +2008-10-04 : Igor Pavlov : Public domain */
    14.6 +
    14.7 +#ifndef __LZFIND_H
    14.8 +#define __LZFIND_H
    14.9 +
   14.10 +#include "Types.h"
   14.11 +
   14.12 +typedef UInt32 CLzRef;
   14.13 +
   14.14 +typedef struct _CMatchFinder
   14.15 +{
   14.16 +  Byte *buffer;
   14.17 +  UInt32 pos;
   14.18 +  UInt32 posLimit;
   14.19 +  UInt32 streamPos;
   14.20 +  UInt32 lenLimit;
   14.21 +
   14.22 +  UInt32 cyclicBufferPos;
   14.23 +  UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
   14.24 +
   14.25 +  UInt32 matchMaxLen;
   14.26 +  CLzRef *hash;
   14.27 +  CLzRef *son;
   14.28 +  UInt32 hashMask;
   14.29 +  UInt32 cutValue;
   14.30 +
   14.31 +  Byte *bufferBase;
   14.32 +  ISeqInStream *stream;
   14.33 +  int streamEndWasReached;
   14.34 +
   14.35 +  UInt32 blockSize;
   14.36 +  UInt32 keepSizeBefore;
   14.37 +  UInt32 keepSizeAfter;
   14.38 +
   14.39 +  UInt32 numHashBytes;
   14.40 +  int directInput;
   14.41 +  int btMode;
   14.42 +  /* int skipModeBits; */
   14.43 +  int bigHash;
   14.44 +  UInt32 historySize;
   14.45 +  UInt32 fixedHashSize;
   14.46 +  UInt32 hashSizeSum;
   14.47 +  UInt32 numSons;
   14.48 +  SRes result;
   14.49 +  UInt32 crc[256];
   14.50 +} CMatchFinder;
   14.51 +
   14.52 +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
   14.53 +#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
   14.54 +
   14.55 +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
   14.56 +
   14.57 +int MatchFinder_NeedMove(CMatchFinder *p);
   14.58 +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
   14.59 +void MatchFinder_MoveBlock(CMatchFinder *p);
   14.60 +void MatchFinder_ReadIfRequired(CMatchFinder *p);
   14.61 +
   14.62 +void MatchFinder_Construct(CMatchFinder *p);
   14.63 +
   14.64 +/* Conditions:
   14.65 +     historySize <= 3 GB
   14.66 +     keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
   14.67 +*/
   14.68 +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
   14.69 +    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
   14.70 +    ISzAlloc *alloc);
   14.71 +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
   14.72 +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
   14.73 +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
   14.74 +
   14.75 +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
   14.76 +    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
   14.77 +    UInt32 *distances, UInt32 maxLen);
   14.78 +
   14.79 +/*
   14.80 +Conditions:
   14.81 +  Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
   14.82 +  Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
   14.83 +*/
   14.84 +
   14.85 +typedef void (*Mf_Init_Func)(void *object);
   14.86 +typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
   14.87 +typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
   14.88 +typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
   14.89 +typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
   14.90 +typedef void (*Mf_Skip_Func)(void *object, UInt32);
   14.91 +
   14.92 +typedef struct _IMatchFinder
   14.93 +{
   14.94 +  Mf_Init_Func Init;
   14.95 +  Mf_GetIndexByte_Func GetIndexByte;
   14.96 +  Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
   14.97 +  Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
   14.98 +  Mf_GetMatches_Func GetMatches;
   14.99 +  Mf_Skip_Func Skip;
  14.100 +} IMatchFinder;
  14.101 +
  14.102 +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
  14.103 +
  14.104 +void MatchFinder_Init(CMatchFinder *p);
  14.105 +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
  14.106 +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
  14.107 +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
  14.108 +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
  14.109 +
  14.110 +#endif
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/libs/openctm/liblzma/LzHash.h	Thu Sep 26 04:47:05 2013 +0300
    15.3 @@ -0,0 +1,54 @@
    15.4 +/* LzHash.h -- HASH functions for LZ algorithms
    15.5 +2008-10-04 : Igor Pavlov : Public domain */
    15.6 +
    15.7 +#ifndef __LZHASH_H
    15.8 +#define __LZHASH_H
    15.9 +
   15.10 +#define kHash2Size (1 << 10)
   15.11 +#define kHash3Size (1 << 16)
   15.12 +#define kHash4Size (1 << 20)
   15.13 +
   15.14 +#define kFix3HashSize (kHash2Size)
   15.15 +#define kFix4HashSize (kHash2Size + kHash3Size)
   15.16 +#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
   15.17 +
   15.18 +#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
   15.19 +
   15.20 +#define HASH3_CALC { \
   15.21 +  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
   15.22 +  hash2Value = temp & (kHash2Size - 1); \
   15.23 +  hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
   15.24 +
   15.25 +#define HASH4_CALC { \
   15.26 +  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
   15.27 +  hash2Value = temp & (kHash2Size - 1); \
   15.28 +  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
   15.29 +  hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
   15.30 +
   15.31 +#define HASH5_CALC { \
   15.32 +  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
   15.33 +  hash2Value = temp & (kHash2Size - 1); \
   15.34 +  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
   15.35 +  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
   15.36 +  hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
   15.37 +  hash4Value &= (kHash4Size - 1); }
   15.38 +
   15.39 +/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
   15.40 +#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
   15.41 +
   15.42 +
   15.43 +#define MT_HASH2_CALC \
   15.44 +  hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
   15.45 +
   15.46 +#define MT_HASH3_CALC { \
   15.47 +  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
   15.48 +  hash2Value = temp & (kHash2Size - 1); \
   15.49 +  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
   15.50 +
   15.51 +#define MT_HASH4_CALC { \
   15.52 +  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
   15.53 +  hash2Value = temp & (kHash2Size - 1); \
   15.54 +  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
   15.55 +  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
   15.56 +
   15.57 +#endif
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/libs/openctm/liblzma/LzmaDec.c	Thu Sep 26 04:47:05 2013 +0300
    16.3 @@ -0,0 +1,1007 @@
    16.4 +/* LzmaDec.c -- LZMA Decoder
    16.5 +2008-11-06 : Igor Pavlov : Public domain */
    16.6 +
    16.7 +#include "LzmaDec.h"
    16.8 +
    16.9 +#include <string.h>
   16.10 +
   16.11 +#define kNumTopBits 24
   16.12 +#define kTopValue ((UInt32)1 << kNumTopBits)
   16.13 +
   16.14 +#define kNumBitModelTotalBits 11
   16.15 +#define kBitModelTotal (1 << kNumBitModelTotalBits)
   16.16 +#define kNumMoveBits 5
   16.17 +
   16.18 +#define RC_INIT_SIZE 5
   16.19 +
   16.20 +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
   16.21 +
   16.22 +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
   16.23 +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
   16.24 +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
   16.25 +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
   16.26 +  { UPDATE_0(p); i = (i + i); A0; } else \
   16.27 +  { UPDATE_1(p); i = (i + i) + 1; A1; }
   16.28 +#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
   16.29 +
   16.30 +#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
   16.31 +#define TREE_DECODE(probs, limit, i) \
   16.32 +  { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
   16.33 +
   16.34 +/* #define _LZMA_SIZE_OPT */
   16.35 +
   16.36 +#ifdef _LZMA_SIZE_OPT
   16.37 +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
   16.38 +#else
   16.39 +#define TREE_6_DECODE(probs, i) \
   16.40 +  { i = 1; \
   16.41 +  TREE_GET_BIT(probs, i); \
   16.42 +  TREE_GET_BIT(probs, i); \
   16.43 +  TREE_GET_BIT(probs, i); \
   16.44 +  TREE_GET_BIT(probs, i); \
   16.45 +  TREE_GET_BIT(probs, i); \
   16.46 +  TREE_GET_BIT(probs, i); \
   16.47 +  i -= 0x40; }
   16.48 +#endif
   16.49 +
   16.50 +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
   16.51 +
   16.52 +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
   16.53 +#define UPDATE_0_CHECK range = bound;
   16.54 +#define UPDATE_1_CHECK range -= bound; code -= bound;
   16.55 +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
   16.56 +  { UPDATE_0_CHECK; i = (i + i); A0; } else \
   16.57 +  { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
   16.58 +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
   16.59 +#define TREE_DECODE_CHECK(probs, limit, i) \
   16.60 +  { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
   16.61 +
   16.62 +
   16.63 +#define kNumPosBitsMax 4
   16.64 +#define kNumPosStatesMax (1 << kNumPosBitsMax)
   16.65 +
   16.66 +#define kLenNumLowBits 3
   16.67 +#define kLenNumLowSymbols (1 << kLenNumLowBits)
   16.68 +#define kLenNumMidBits 3
   16.69 +#define kLenNumMidSymbols (1 << kLenNumMidBits)
   16.70 +#define kLenNumHighBits 8
   16.71 +#define kLenNumHighSymbols (1 << kLenNumHighBits)
   16.72 +
   16.73 +#define LenChoice 0
   16.74 +#define LenChoice2 (LenChoice + 1)
   16.75 +#define LenLow (LenChoice2 + 1)
   16.76 +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
   16.77 +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
   16.78 +#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
   16.79 +
   16.80 +
   16.81 +#define kNumStates 12
   16.82 +#define kNumLitStates 7
   16.83 +
   16.84 +#define kStartPosModelIndex 4
   16.85 +#define kEndPosModelIndex 14
   16.86 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
   16.87 +
   16.88 +#define kNumPosSlotBits 6
   16.89 +#define kNumLenToPosStates 4
   16.90 +
   16.91 +#define kNumAlignBits 4
   16.92 +#define kAlignTableSize (1 << kNumAlignBits)
   16.93 +
   16.94 +#define kMatchMinLen 2
   16.95 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
   16.96 +
   16.97 +#define IsMatch 0
   16.98 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
   16.99 +#define IsRepG0 (IsRep + kNumStates)
  16.100 +#define IsRepG1 (IsRepG0 + kNumStates)
  16.101 +#define IsRepG2 (IsRepG1 + kNumStates)
  16.102 +#define IsRep0Long (IsRepG2 + kNumStates)
  16.103 +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
  16.104 +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
  16.105 +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
  16.106 +#define LenCoder (Align + kAlignTableSize)
  16.107 +#define RepLenCoder (LenCoder + kNumLenProbs)
  16.108 +#define Literal (RepLenCoder + kNumLenProbs)
  16.109 +
  16.110 +#define LZMA_BASE_SIZE 1846
  16.111 +#define LZMA_LIT_SIZE 768
  16.112 +
  16.113 +#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
  16.114 +
  16.115 +#if Literal != LZMA_BASE_SIZE
  16.116 +StopCompilingDueBUG
  16.117 +#endif
  16.118 +
  16.119 +static const Byte kLiteralNextStates[kNumStates * 2] =
  16.120 +{
  16.121 +  0, 0, 0, 0, 1, 2, 3,  4,  5,  6,  4,  5,
  16.122 +  7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10
  16.123 +};
  16.124 +
  16.125 +#define LZMA_DIC_MIN (1 << 12)
  16.126 +
  16.127 +/* First LZMA-symbol is always decoded.
  16.128 +And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
  16.129 +Out:
  16.130 +  Result:
  16.131 +    SZ_OK - OK
  16.132 +    SZ_ERROR_DATA - Error
  16.133 +  p->remainLen:
  16.134 +    < kMatchSpecLenStart : normal remain
  16.135 +    = kMatchSpecLenStart : finished
  16.136 +    = kMatchSpecLenStart + 1 : Flush marker
  16.137 +    = kMatchSpecLenStart + 2 : State Init Marker
  16.138 +*/
  16.139 +
  16.140 +static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
  16.141 +{
  16.142 +  CLzmaProb *probs = p->probs;
  16.143 +
  16.144 +  unsigned state = p->state;
  16.145 +  UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
  16.146 +  unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
  16.147 +  unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
  16.148 +  unsigned lc = p->prop.lc;
  16.149 +
  16.150 +  Byte *dic = p->dic;
  16.151 +  SizeT dicBufSize = p->dicBufSize;
  16.152 +  SizeT dicPos = p->dicPos;
  16.153 +  
  16.154 +  UInt32 processedPos = p->processedPos;
  16.155 +  UInt32 checkDicSize = p->checkDicSize;
  16.156 +  unsigned len = 0;
  16.157 +
  16.158 +  const Byte *buf = p->buf;
  16.159 +  UInt32 range = p->range;
  16.160 +  UInt32 code = p->code;
  16.161 +
  16.162 +  do
  16.163 +  {
  16.164 +    CLzmaProb *prob;
  16.165 +    UInt32 bound;
  16.166 +    unsigned ttt;
  16.167 +    unsigned posState = processedPos & pbMask;
  16.168 +
  16.169 +    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
  16.170 +    IF_BIT_0(prob)
  16.171 +    {
  16.172 +      unsigned symbol;
  16.173 +      UPDATE_0(prob);
  16.174 +      prob = probs + Literal;
  16.175 +      if (checkDicSize != 0 || processedPos != 0)
  16.176 +        prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
  16.177 +        (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
  16.178 +
  16.179 +      if (state < kNumLitStates)
  16.180 +      {
  16.181 +        symbol = 1;
  16.182 +        do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
  16.183 +      }
  16.184 +      else
  16.185 +      {
  16.186 +        unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
  16.187 +        unsigned offs = 0x100;
  16.188 +        symbol = 1;
  16.189 +        do
  16.190 +        {
  16.191 +          unsigned bit;
  16.192 +          CLzmaProb *probLit;
  16.193 +          matchByte <<= 1;
  16.194 +          bit = (matchByte & offs);
  16.195 +          probLit = prob + offs + bit + symbol;
  16.196 +          GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
  16.197 +        }
  16.198 +        while (symbol < 0x100);
  16.199 +      }
  16.200 +      dic[dicPos++] = (Byte)symbol;
  16.201 +      processedPos++;
  16.202 +
  16.203 +      state = kLiteralNextStates[state];
  16.204 +      /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */
  16.205 +      continue;
  16.206 +    }
  16.207 +    else
  16.208 +    {
  16.209 +      UPDATE_1(prob);
  16.210 +      prob = probs + IsRep + state;
  16.211 +      IF_BIT_0(prob)
  16.212 +      {
  16.213 +        UPDATE_0(prob);
  16.214 +        state += kNumStates;
  16.215 +        prob = probs + LenCoder;
  16.216 +      }
  16.217 +      else
  16.218 +      {
  16.219 +        UPDATE_1(prob);
  16.220 +        if (checkDicSize == 0 && processedPos == 0)
  16.221 +          return SZ_ERROR_DATA;
  16.222 +        prob = probs + IsRepG0 + state;
  16.223 +        IF_BIT_0(prob)
  16.224 +        {
  16.225 +          UPDATE_0(prob);
  16.226 +          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
  16.227 +          IF_BIT_0(prob)
  16.228 +          {
  16.229 +            UPDATE_0(prob);
  16.230 +            dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
  16.231 +            dicPos++;
  16.232 +            processedPos++;
  16.233 +            state = state < kNumLitStates ? 9 : 11;
  16.234 +            continue;
  16.235 +          }
  16.236 +          UPDATE_1(prob);
  16.237 +        }
  16.238 +        else
  16.239 +        {
  16.240 +          UInt32 distance;
  16.241 +          UPDATE_1(prob);
  16.242 +          prob = probs + IsRepG1 + state;
  16.243 +          IF_BIT_0(prob)
  16.244 +          {
  16.245 +            UPDATE_0(prob);
  16.246 +            distance = rep1;
  16.247 +          }
  16.248 +          else
  16.249 +          {
  16.250 +            UPDATE_1(prob);
  16.251 +            prob = probs + IsRepG2 + state;
  16.252 +            IF_BIT_0(prob)
  16.253 +            {
  16.254 +              UPDATE_0(prob);
  16.255 +              distance = rep2;
  16.256 +            }
  16.257 +            else
  16.258 +            {
  16.259 +              UPDATE_1(prob);
  16.260 +              distance = rep3;
  16.261 +              rep3 = rep2;
  16.262 +            }
  16.263 +            rep2 = rep1;
  16.264 +          }
  16.265 +          rep1 = rep0;
  16.266 +          rep0 = distance;
  16.267 +        }
  16.268 +        state = state < kNumLitStates ? 8 : 11;
  16.269 +        prob = probs + RepLenCoder;
  16.270 +      }
  16.271 +      {
  16.272 +        unsigned limit, offset;
  16.273 +        CLzmaProb *probLen = prob + LenChoice;
  16.274 +        IF_BIT_0(probLen)
  16.275 +        {
  16.276 +          UPDATE_0(probLen);
  16.277 +          probLen = prob + LenLow + (posState << kLenNumLowBits);
  16.278 +          offset = 0;
  16.279 +          limit = (1 << kLenNumLowBits);
  16.280 +        }
  16.281 +        else
  16.282 +        {
  16.283 +          UPDATE_1(probLen);
  16.284 +          probLen = prob + LenChoice2;
  16.285 +          IF_BIT_0(probLen)
  16.286 +          {
  16.287 +            UPDATE_0(probLen);
  16.288 +            probLen = prob + LenMid + (posState << kLenNumMidBits);
  16.289 +            offset = kLenNumLowSymbols;
  16.290 +            limit = (1 << kLenNumMidBits);
  16.291 +          }
  16.292 +          else
  16.293 +          {
  16.294 +            UPDATE_1(probLen);
  16.295 +            probLen = prob + LenHigh;
  16.296 +            offset = kLenNumLowSymbols + kLenNumMidSymbols;
  16.297 +            limit = (1 << kLenNumHighBits);
  16.298 +          }
  16.299 +        }
  16.300 +        TREE_DECODE(probLen, limit, len);
  16.301 +        len += offset;
  16.302 +      }
  16.303 +
  16.304 +      if (state >= kNumStates)
  16.305 +      {
  16.306 +        UInt32 distance;
  16.307 +        prob = probs + PosSlot +
  16.308 +            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
  16.309 +        TREE_6_DECODE(prob, distance);
  16.310 +        if (distance >= kStartPosModelIndex)
  16.311 +        {
  16.312 +          unsigned posSlot = (unsigned)distance;
  16.313 +          int numDirectBits = (int)(((distance >> 1) - 1));
  16.314 +          distance = (2 | (distance & 1));
  16.315 +          if (posSlot < kEndPosModelIndex)
  16.316 +          {
  16.317 +            distance <<= numDirectBits;
  16.318 +            prob = probs + SpecPos + distance - posSlot - 1;
  16.319 +            {
  16.320 +              UInt32 mask = 1;
  16.321 +              unsigned i = 1;
  16.322 +              do
  16.323 +              {
  16.324 +                GET_BIT2(prob + i, i, ; , distance |= mask);
  16.325 +                mask <<= 1;
  16.326 +              }
  16.327 +              while (--numDirectBits != 0);
  16.328 +            }
  16.329 +          }
  16.330 +          else
  16.331 +          {
  16.332 +            numDirectBits -= kNumAlignBits;
  16.333 +            do
  16.334 +            {
  16.335 +              NORMALIZE
  16.336 +              range >>= 1;
  16.337 +              
  16.338 +              {
  16.339 +                UInt32 t;
  16.340 +                code -= range;
  16.341 +                t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
  16.342 +                distance = (distance << 1) + (t + 1);
  16.343 +                code += range & t;
  16.344 +              }
  16.345 +              /*
  16.346 +              distance <<= 1;
  16.347 +              if (code >= range)
  16.348 +              {
  16.349 +                code -= range;
  16.350 +                distance |= 1;
  16.351 +              }
  16.352 +              */
  16.353 +            }
  16.354 +            while (--numDirectBits != 0);
  16.355 +            prob = probs + Align;
  16.356 +            distance <<= kNumAlignBits;
  16.357 +            {
  16.358 +              unsigned i = 1;
  16.359 +              GET_BIT2(prob + i, i, ; , distance |= 1);
  16.360 +              GET_BIT2(prob + i, i, ; , distance |= 2);
  16.361 +              GET_BIT2(prob + i, i, ; , distance |= 4);
  16.362 +              GET_BIT2(prob + i, i, ; , distance |= 8);
  16.363 +            }
  16.364 +            if (distance == (UInt32)0xFFFFFFFF)
  16.365 +            {
  16.366 +              len += kMatchSpecLenStart;
  16.367 +              state -= kNumStates;
  16.368 +              break;
  16.369 +            }
  16.370 +          }
  16.371 +        }
  16.372 +        rep3 = rep2;
  16.373 +        rep2 = rep1;
  16.374 +        rep1 = rep0;
  16.375 +        rep0 = distance + 1;
  16.376 +        if (checkDicSize == 0)
  16.377 +        {
  16.378 +          if (distance >= processedPos)
  16.379 +            return SZ_ERROR_DATA;
  16.380 +        }
  16.381 +        else if (distance >= checkDicSize)
  16.382 +          return SZ_ERROR_DATA;
  16.383 +        state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
  16.384 +        /* state = kLiteralNextStates[state]; */
  16.385 +      }
  16.386 +
  16.387 +      len += kMatchMinLen;
  16.388 +
  16.389 +      if (limit == dicPos)
  16.390 +        return SZ_ERROR_DATA;
  16.391 +      {
  16.392 +        SizeT rem = limit - dicPos;
  16.393 +        unsigned curLen = ((rem < len) ? (unsigned)rem : len);
  16.394 +        SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
  16.395 +
  16.396 +        processedPos += curLen;
  16.397 +
  16.398 +        len -= curLen;
  16.399 +        if (pos + curLen <= dicBufSize)
  16.400 +        {
  16.401 +          Byte *dest = dic + dicPos;
  16.402 +          ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
  16.403 +          const Byte *lim = dest + curLen;
  16.404 +          dicPos += curLen;
  16.405 +          do
  16.406 +            *(dest) = (Byte)*(dest + src);
  16.407 +          while (++dest != lim);
  16.408 +        }
  16.409 +        else
  16.410 +        {
  16.411 +          do
  16.412 +          {
  16.413 +            dic[dicPos++] = dic[pos];
  16.414 +            if (++pos == dicBufSize)
  16.415 +              pos = 0;
  16.416 +          }
  16.417 +          while (--curLen != 0);
  16.418 +        }
  16.419 +      }
  16.420 +    }
  16.421 +  }
  16.422 +  while (dicPos < limit && buf < bufLimit);
  16.423 +  NORMALIZE;
  16.424 +  p->buf = buf;
  16.425 +  p->range = range;
  16.426 +  p->code = code;
  16.427 +  p->remainLen = len;
  16.428 +  p->dicPos = dicPos;
  16.429 +  p->processedPos = processedPos;
  16.430 +  p->reps[0] = rep0;
  16.431 +  p->reps[1] = rep1;
  16.432 +  p->reps[2] = rep2;
  16.433 +  p->reps[3] = rep3;
  16.434 +  p->state = state;
  16.435 +
  16.436 +  return SZ_OK;
  16.437 +}
  16.438 +
  16.439 +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
  16.440 +{
  16.441 +  if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
  16.442 +  {
  16.443 +    Byte *dic = p->dic;
  16.444 +    SizeT dicPos = p->dicPos;
  16.445 +    SizeT dicBufSize = p->dicBufSize;
  16.446 +    unsigned len = p->remainLen;
  16.447 +    UInt32 rep0 = p->reps[0];
  16.448 +    if (limit - dicPos < len)
  16.449 +      len = (unsigned)(limit - dicPos);
  16.450 +
  16.451 +    if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
  16.452 +      p->checkDicSize = p->prop.dicSize;
  16.453 +
  16.454 +    p->processedPos += len;
  16.455 +    p->remainLen -= len;
  16.456 +    while (len-- != 0)
  16.457 +    {
  16.458 +      dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
  16.459 +      dicPos++;
  16.460 +    }
  16.461 +    p->dicPos = dicPos;
  16.462 +  }
  16.463 +}
  16.464 +
  16.465 +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
  16.466 +{
  16.467 +  do
  16.468 +  {
  16.469 +    SizeT limit2 = limit;
  16.470 +    if (p->checkDicSize == 0)
  16.471 +    {
  16.472 +      UInt32 rem = p->prop.dicSize - p->processedPos;
  16.473 +      if (limit - p->dicPos > rem)
  16.474 +        limit2 = p->dicPos + rem;
  16.475 +    }
  16.476 +    RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
  16.477 +    if (p->processedPos >= p->prop.dicSize)
  16.478 +      p->checkDicSize = p->prop.dicSize;
  16.479 +    LzmaDec_WriteRem(p, limit);
  16.480 +  }
  16.481 +  while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
  16.482 +
  16.483 +  if (p->remainLen > kMatchSpecLenStart)
  16.484 +  {
  16.485 +    p->remainLen = kMatchSpecLenStart;
  16.486 +  }
  16.487 +  return 0;
  16.488 +}
  16.489 +
  16.490 +typedef enum
  16.491 +{
  16.492 +  DUMMY_ERROR, /* unexpected end of input stream */
  16.493 +  DUMMY_LIT,
  16.494 +  DUMMY_MATCH,
  16.495 +  DUMMY_REP
  16.496 +} ELzmaDummy;
  16.497 +
  16.498 +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
  16.499 +{
  16.500 +  UInt32 range = p->range;
  16.501 +  UInt32 code = p->code;
  16.502 +  const Byte *bufLimit = buf + inSize;
  16.503 +  CLzmaProb *probs = p->probs;
  16.504 +  unsigned state = p->state;
  16.505 +  ELzmaDummy res;
  16.506 +
  16.507 +  {
  16.508 +    CLzmaProb *prob;
  16.509 +    UInt32 bound;
  16.510 +    unsigned ttt;
  16.511 +    unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
  16.512 +
  16.513 +    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
  16.514 +    IF_BIT_0_CHECK(prob)
  16.515 +    {
  16.516 +      UPDATE_0_CHECK
  16.517 +
  16.518 +      /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
  16.519 +
  16.520 +      prob = probs + Literal;
  16.521 +      if (p->checkDicSize != 0 || p->processedPos != 0)
  16.522 +        prob += (LZMA_LIT_SIZE *
  16.523 +          ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
  16.524 +          (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
  16.525 +
  16.526 +      if (state < kNumLitStates)
  16.527 +      {
  16.528 +        unsigned symbol = 1;
  16.529 +        do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
  16.530 +      }
  16.531 +      else
  16.532 +      {
  16.533 +        unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
  16.534 +            ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
  16.535 +        unsigned offs = 0x100;
  16.536 +        unsigned symbol = 1;
  16.537 +        do
  16.538 +        {
  16.539 +          unsigned bit;
  16.540 +          CLzmaProb *probLit;
  16.541 +          matchByte <<= 1;
  16.542 +          bit = (matchByte & offs);
  16.543 +          probLit = prob + offs + bit + symbol;
  16.544 +          GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
  16.545 +        }
  16.546 +        while (symbol < 0x100);
  16.547 +      }
  16.548 +      res = DUMMY_LIT;
  16.549 +    }
  16.550 +    else
  16.551 +    {
  16.552 +      unsigned len;
  16.553 +      UPDATE_1_CHECK;
  16.554 +
  16.555 +      prob = probs + IsRep + state;
  16.556 +      IF_BIT_0_CHECK(prob)
  16.557 +      {
  16.558 +        UPDATE_0_CHECK;
  16.559 +        state = 0;
  16.560 +        prob = probs + LenCoder;
  16.561 +        res = DUMMY_MATCH;
  16.562 +      }
  16.563 +      else
  16.564 +      {
  16.565 +        UPDATE_1_CHECK;
  16.566 +        res = DUMMY_REP;
  16.567 +        prob = probs + IsRepG0 + state;
  16.568 +        IF_BIT_0_CHECK(prob)
  16.569 +        {
  16.570 +          UPDATE_0_CHECK;
  16.571 +          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
  16.572 +          IF_BIT_0_CHECK(prob)
  16.573 +          {
  16.574 +            UPDATE_0_CHECK;
  16.575 +            NORMALIZE_CHECK;
  16.576 +            return DUMMY_REP;
  16.577 +          }
  16.578 +          else
  16.579 +          {
  16.580 +            UPDATE_1_CHECK;
  16.581 +          }
  16.582 +        }
  16.583 +        else
  16.584 +        {
  16.585 +          UPDATE_1_CHECK;
  16.586 +          prob = probs + IsRepG1 + state;
  16.587 +          IF_BIT_0_CHECK(prob)
  16.588 +          {
  16.589 +            UPDATE_0_CHECK;
  16.590 +          }
  16.591 +          else
  16.592 +          {
  16.593 +            UPDATE_1_CHECK;
  16.594 +            prob = probs + IsRepG2 + state;
  16.595 +            IF_BIT_0_CHECK(prob)
  16.596 +            {
  16.597 +              UPDATE_0_CHECK;
  16.598 +            }
  16.599 +            else
  16.600 +            {
  16.601 +              UPDATE_1_CHECK;
  16.602 +            }
  16.603 +          }
  16.604 +        }
  16.605 +        state = kNumStates;
  16.606 +        prob = probs + RepLenCoder;
  16.607 +      }
  16.608 +      {
  16.609 +        unsigned limit, offset;
  16.610 +        CLzmaProb *probLen = prob + LenChoice;
  16.611 +        IF_BIT_0_CHECK(probLen)
  16.612 +        {
  16.613 +          UPDATE_0_CHECK;
  16.614 +          probLen = prob + LenLow + (posState << kLenNumLowBits);
  16.615 +          offset = 0;
  16.616 +          limit = 1 << kLenNumLowBits;
  16.617 +        }
  16.618 +        else
  16.619 +        {
  16.620 +          UPDATE_1_CHECK;
  16.621 +          probLen = prob + LenChoice2;
  16.622 +          IF_BIT_0_CHECK(probLen)
  16.623 +          {
  16.624 +            UPDATE_0_CHECK;
  16.625 +            probLen = prob + LenMid + (posState << kLenNumMidBits);
  16.626 +            offset = kLenNumLowSymbols;
  16.627 +            limit = 1 << kLenNumMidBits;
  16.628 +          }
  16.629 +          else
  16.630 +          {
  16.631 +            UPDATE_1_CHECK;
  16.632 +            probLen = prob + LenHigh;
  16.633 +            offset = kLenNumLowSymbols + kLenNumMidSymbols;
  16.634 +            limit = 1 << kLenNumHighBits;
  16.635 +          }
  16.636 +        }
  16.637 +        TREE_DECODE_CHECK(probLen, limit, len);
  16.638 +        len += offset;
  16.639 +      }
  16.640 +
  16.641 +      if (state < 4)
  16.642 +      {
  16.643 +        unsigned posSlot;
  16.644 +        prob = probs + PosSlot +
  16.645 +            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
  16.646 +            kNumPosSlotBits);
  16.647 +        TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
  16.648 +        if (posSlot >= kStartPosModelIndex)
  16.649 +        {
  16.650 +          int numDirectBits = ((posSlot >> 1) - 1);
  16.651 +
  16.652 +          /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
  16.653 +
  16.654 +          if (posSlot < kEndPosModelIndex)
  16.655 +          {
  16.656 +            prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
  16.657 +          }
  16.658 +          else
  16.659 +          {
  16.660 +            numDirectBits -= kNumAlignBits;
  16.661 +            do
  16.662 +            {
  16.663 +              NORMALIZE_CHECK
  16.664 +              range >>= 1;
  16.665 +              code -= range & (((code - range) >> 31) - 1);
  16.666 +              /* if (code >= range) code -= range; */
  16.667 +            }
  16.668 +            while (--numDirectBits != 0);
  16.669 +            prob = probs + Align;
  16.670 +            numDirectBits = kNumAlignBits;
  16.671 +          }
  16.672 +          {
  16.673 +            unsigned i = 1;
  16.674 +            do
  16.675 +            {
  16.676 +              GET_BIT_CHECK(prob + i, i);
  16.677 +            }
  16.678 +            while (--numDirectBits != 0);
  16.679 +          }
  16.680 +        }
  16.681 +      }
  16.682 +    }
  16.683 +  }
  16.684 +  NORMALIZE_CHECK;
  16.685 +  return res;
  16.686 +}
  16.687 +
  16.688 +
  16.689 +static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
  16.690 +{
  16.691 +  p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
  16.692 +  p->range = 0xFFFFFFFF;
  16.693 +  p->needFlush = 0;
  16.694 +}
  16.695 +
  16.696 +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
  16.697 +{
  16.698 +  p->needFlush = 1;
  16.699 +  p->remainLen = 0;
  16.700 +  p->tempBufSize = 0;
  16.701 +
  16.702 +  if (initDic)
  16.703 +  {
  16.704 +    p->processedPos = 0;
  16.705 +    p->checkDicSize = 0;
  16.706 +    p->needInitState = 1;
  16.707 +  }
  16.708 +  if (initState)
  16.709 +    p->needInitState = 1;
  16.710 +}
  16.711 +
  16.712 +void LzmaDec_Init(CLzmaDec *p)
  16.713 +{
  16.714 +  p->dicPos = 0;
  16.715 +  LzmaDec_InitDicAndState(p, True, True);
  16.716 +}
  16.717 +
  16.718 +static void LzmaDec_InitStateReal(CLzmaDec *p)
  16.719 +{
  16.720 +  UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
  16.721 +  UInt32 i;
  16.722 +  CLzmaProb *probs = p->probs;
  16.723 +  for (i = 0; i < numProbs; i++)
  16.724 +    probs[i] = kBitModelTotal >> 1;
  16.725 +  p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
  16.726 +  p->state = 0;
  16.727 +  p->needInitState = 0;
  16.728 +}
  16.729 +
  16.730 +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
  16.731 +    ELzmaFinishMode finishMode, ELzmaStatus *status)
  16.732 +{
  16.733 +  SizeT inSize = *srcLen;
  16.734 +  (*srcLen) = 0;
  16.735 +  LzmaDec_WriteRem(p, dicLimit);
  16.736 +  
  16.737 +  *status = LZMA_STATUS_NOT_SPECIFIED;
  16.738 +
  16.739 +  while (p->remainLen != kMatchSpecLenStart)
  16.740 +  {
  16.741 +      int checkEndMarkNow;
  16.742 +
  16.743 +      if (p->needFlush != 0)
  16.744 +      {
  16.745 +        for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
  16.746 +          p->tempBuf[p->tempBufSize++] = *src++;
  16.747 +        if (p->tempBufSize < RC_INIT_SIZE)
  16.748 +        {
  16.749 +          *status = LZMA_STATUS_NEEDS_MORE_INPUT;
  16.750 +          return SZ_OK;
  16.751 +        }
  16.752 +        if (p->tempBuf[0] != 0)
  16.753 +          return SZ_ERROR_DATA;
  16.754 +
  16.755 +        LzmaDec_InitRc(p, p->tempBuf);
  16.756 +        p->tempBufSize = 0;
  16.757 +      }
  16.758 +
  16.759 +      checkEndMarkNow = 0;
  16.760 +      if (p->dicPos >= dicLimit)
  16.761 +      {
  16.762 +        if (p->remainLen == 0 && p->code == 0)
  16.763 +        {
  16.764 +          *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
  16.765 +          return SZ_OK;
  16.766 +        }
  16.767 +        if (finishMode == LZMA_FINISH_ANY)
  16.768 +        {
  16.769 +          *status = LZMA_STATUS_NOT_FINISHED;
  16.770 +          return SZ_OK;
  16.771 +        }
  16.772 +        if (p->remainLen != 0)
  16.773 +        {
  16.774 +          *status = LZMA_STATUS_NOT_FINISHED;
  16.775 +          return SZ_ERROR_DATA;
  16.776 +        }
  16.777 +        checkEndMarkNow = 1;
  16.778 +      }
  16.779 +
  16.780 +      if (p->needInitState)
  16.781 +        LzmaDec_InitStateReal(p);
  16.782 +  
  16.783 +      if (p->tempBufSize == 0)
  16.784 +      {
  16.785 +        SizeT processed;
  16.786 +        const Byte *bufLimit;
  16.787 +        if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
  16.788 +        {
  16.789 +          int dummyRes = LzmaDec_TryDummy(p, src, inSize);
  16.790 +          if (dummyRes == DUMMY_ERROR)
  16.791 +          {
  16.792 +            memcpy(p->tempBuf, src, inSize);
  16.793 +            p->tempBufSize = (unsigned)inSize;
  16.794 +            (*srcLen) += inSize;
  16.795 +            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
  16.796 +            return SZ_OK;
  16.797 +          }
  16.798 +          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
  16.799 +          {
  16.800 +            *status = LZMA_STATUS_NOT_FINISHED;
  16.801 +            return SZ_ERROR_DATA;
  16.802 +          }
  16.803 +          bufLimit = src;
  16.804 +        }
  16.805 +        else
  16.806 +          bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
  16.807 +        p->buf = src;
  16.808 +        if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
  16.809 +          return SZ_ERROR_DATA;
  16.810 +        processed = (SizeT)(p->buf - src);
  16.811 +        (*srcLen) += processed;
  16.812 +        src += processed;
  16.813 +        inSize -= processed;
  16.814 +      }
  16.815 +      else
  16.816 +      {
  16.817 +        unsigned rem = p->tempBufSize, lookAhead = 0;
  16.818 +        while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
  16.819 +          p->tempBuf[rem++] = src[lookAhead++];
  16.820 +        p->tempBufSize = rem;
  16.821 +        if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
  16.822 +        {
  16.823 +          int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
  16.824 +          if (dummyRes == DUMMY_ERROR)
  16.825 +          {
  16.826 +            (*srcLen) += lookAhead;
  16.827 +            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
  16.828 +            return SZ_OK;
  16.829 +          }
  16.830 +          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
  16.831 +          {
  16.832 +            *status = LZMA_STATUS_NOT_FINISHED;
  16.833 +            return SZ_ERROR_DATA;
  16.834 +          }
  16.835 +        }
  16.836 +        p->buf = p->tempBuf;
  16.837 +        if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
  16.838 +          return SZ_ERROR_DATA;
  16.839 +        lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
  16.840 +        (*srcLen) += lookAhead;
  16.841 +        src += lookAhead;
  16.842 +        inSize -= lookAhead;
  16.843 +        p->tempBufSize = 0;
  16.844 +      }
  16.845 +  }
  16.846 +  if (p->code == 0)
  16.847 +    *status = LZMA_STATUS_FINISHED_WITH_MARK;
  16.848 +  return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
  16.849 +}
  16.850 +
  16.851 +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
  16.852 +{
  16.853 +  SizeT outSize = *destLen;
  16.854 +  SizeT inSize = *srcLen;
  16.855 +  *srcLen = *destLen = 0;
  16.856 +  for (;;)
  16.857 +  {
  16.858 +    SizeT inSizeCur = inSize, outSizeCur, dicPos;
  16.859 +    ELzmaFinishMode curFinishMode;
  16.860 +    SRes res;
  16.861 +    if (p->dicPos == p->dicBufSize)
  16.862 +      p->dicPos = 0;
  16.863 +    dicPos = p->dicPos;
  16.864 +    if (outSize > p->dicBufSize - dicPos)
  16.865 +    {
  16.866 +      outSizeCur = p->dicBufSize;
  16.867 +      curFinishMode = LZMA_FINISH_ANY;
  16.868 +    }
  16.869 +    else
  16.870 +    {
  16.871 +      outSizeCur = dicPos + outSize;
  16.872 +      curFinishMode = finishMode;
  16.873 +    }
  16.874 +
  16.875 +    res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
  16.876 +    src += inSizeCur;
  16.877 +    inSize -= inSizeCur;
  16.878 +    *srcLen += inSizeCur;
  16.879 +    outSizeCur = p->dicPos - dicPos;
  16.880 +    memcpy(dest, p->dic + dicPos, outSizeCur);
  16.881 +    dest += outSizeCur;
  16.882 +    outSize -= outSizeCur;
  16.883 +    *destLen += outSizeCur;
  16.884 +    if (res != 0)
  16.885 +      return res;
  16.886 +    if (outSizeCur == 0 || outSize == 0)
  16.887 +      return SZ_OK;
  16.888 +  }
  16.889 +}
  16.890 +
  16.891 +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
  16.892 +{
  16.893 +  alloc->Free(alloc, p->probs);
  16.894 +  p->probs = 0;
  16.895 +}
  16.896 +
  16.897 +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
  16.898 +{
  16.899 +  alloc->Free(alloc, p->dic);
  16.900 +  p->dic = 0;
  16.901 +}
  16.902 +
  16.903 +void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
  16.904 +{
  16.905 +  LzmaDec_FreeProbs(p, alloc);
  16.906 +  LzmaDec_FreeDict(p, alloc);
  16.907 +}
  16.908 +
  16.909 +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
  16.910 +{
  16.911 +  UInt32 dicSize;
  16.912 +  Byte d;
  16.913 +  
  16.914 +  if (size < LZMA_PROPS_SIZE)
  16.915 +    return SZ_ERROR_UNSUPPORTED;
  16.916 +  else
  16.917 +    dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
  16.918 + 
  16.919 +  if (dicSize < LZMA_DIC_MIN)
  16.920 +    dicSize = LZMA_DIC_MIN;
  16.921 +  p->dicSize = dicSize;
  16.922 +
  16.923 +  d = data[0];
  16.924 +  if (d >= (9 * 5 * 5))
  16.925 +    return SZ_ERROR_UNSUPPORTED;
  16.926 +
  16.927 +  p->lc = d % 9;
  16.928 +  d /= 9;
  16.929 +  p->pb = d / 5;
  16.930 +  p->lp = d % 5;
  16.931 +
  16.932 +  return SZ_OK;
  16.933 +}
  16.934 +
  16.935 +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
  16.936 +{
  16.937 +  UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
  16.938 +  if (p->probs == 0 || numProbs != p->numProbs)
  16.939 +  {
  16.940 +    LzmaDec_FreeProbs(p, alloc);
  16.941 +    p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
  16.942 +    p->numProbs = numProbs;
  16.943 +    if (p->probs == 0)
  16.944 +      return SZ_ERROR_MEM;
  16.945 +  }
  16.946 +  return SZ_OK;
  16.947 +}
  16.948 +
  16.949 +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
  16.950 +{
  16.951 +  CLzmaProps propNew;
  16.952 +  RINOK(LzmaProps_Decode(&propNew, props, propsSize));
  16.953 +  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
  16.954 +  p->prop = propNew;
  16.955 +  return SZ_OK;
  16.956 +}
  16.957 +
  16.958 +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
  16.959 +{
  16.960 +  CLzmaProps propNew;
  16.961 +  SizeT dicBufSize;
  16.962 +  RINOK(LzmaProps_Decode(&propNew, props, propsSize));
  16.963 +  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
  16.964 +  dicBufSize = propNew.dicSize;
  16.965 +  if (p->dic == 0 || dicBufSize != p->dicBufSize)
  16.966 +  {
  16.967 +    LzmaDec_FreeDict(p, alloc);
  16.968 +    p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
  16.969 +    if (p->dic == 0)
  16.970 +    {
  16.971 +      LzmaDec_FreeProbs(p, alloc);
  16.972 +      return SZ_ERROR_MEM;
  16.973 +    }
  16.974 +  }
  16.975 +  p->dicBufSize = dicBufSize;
  16.976 +  p->prop = propNew;
  16.977 +  return SZ_OK;
  16.978 +}
  16.979 +
  16.980 +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
  16.981 +    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
  16.982 +    ELzmaStatus *status, ISzAlloc *alloc)
  16.983 +{
  16.984 +  CLzmaDec p;
  16.985 +  SRes res;
  16.986 +  SizeT inSize = *srcLen;
  16.987 +  SizeT outSize = *destLen;
  16.988 +  *srcLen = *destLen = 0;
  16.989 +  if (inSize < RC_INIT_SIZE)
  16.990 +    return SZ_ERROR_INPUT_EOF;
  16.991 +
  16.992 +  LzmaDec_Construct(&p);
  16.993 +  res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
  16.994 +  if (res != 0)
  16.995 +    return res;
  16.996 +  p.dic = dest;
  16.997 +  p.dicBufSize = outSize;
  16.998 +
  16.999 +  LzmaDec_Init(&p);
 16.1000 +  
 16.1001 +  *srcLen = inSize;
 16.1002 +  res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
 16.1003 +
 16.1004 +  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
 16.1005 +    res = SZ_ERROR_INPUT_EOF;
 16.1006 +
 16.1007 +  (*destLen) = p.dicPos;
 16.1008 +  LzmaDec_FreeProbs(&p, alloc);
 16.1009 +  return res;
 16.1010 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/libs/openctm/liblzma/LzmaDec.h	Thu Sep 26 04:47:05 2013 +0300
    17.3 @@ -0,0 +1,223 @@
    17.4 +/* LzmaDec.h -- LZMA Decoder
    17.5 +2008-10-04 : Igor Pavlov : Public domain */
    17.6 +
    17.7 +#ifndef __LZMADEC_H
    17.8 +#define __LZMADEC_H
    17.9 +
   17.10 +#include "Types.h"
   17.11 +
   17.12 +/* #define _LZMA_PROB32 */
   17.13 +/* _LZMA_PROB32 can increase the speed on some CPUs,
   17.14 +   but memory usage for CLzmaDec::probs will be doubled in that case */
   17.15 +
   17.16 +#ifdef _LZMA_PROB32
   17.17 +#define CLzmaProb UInt32
   17.18 +#else
   17.19 +#define CLzmaProb UInt16
   17.20 +#endif
   17.21 +
   17.22 +
   17.23 +/* ---------- LZMA Properties ---------- */
   17.24 +
   17.25 +#define LZMA_PROPS_SIZE 5
   17.26 +
   17.27 +typedef struct _CLzmaProps
   17.28 +{
   17.29 +  unsigned lc, lp, pb;
   17.30 +  UInt32 dicSize;
   17.31 +} CLzmaProps;
   17.32 +
   17.33 +/* LzmaProps_Decode - decodes properties
   17.34 +Returns:
   17.35 +  SZ_OK
   17.36 +  SZ_ERROR_UNSUPPORTED - Unsupported properties
   17.37 +*/
   17.38 +
   17.39 +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
   17.40 +
   17.41 +
   17.42 +/* ---------- LZMA Decoder state ---------- */
   17.43 +
   17.44 +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
   17.45 +   Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
   17.46 +
   17.47 +#define LZMA_REQUIRED_INPUT_MAX 20
   17.48 +
   17.49 +typedef struct
   17.50 +{
   17.51 +  CLzmaProps prop;
   17.52 +  CLzmaProb *probs;
   17.53 +  Byte *dic;
   17.54 +  const Byte *buf;
   17.55 +  UInt32 range, code;
   17.56 +  SizeT dicPos;
   17.57 +  SizeT dicBufSize;
   17.58 +  UInt32 processedPos;
   17.59 +  UInt32 checkDicSize;
   17.60 +  unsigned state;
   17.61 +  UInt32 reps[4];
   17.62 +  unsigned remainLen;
   17.63 +  int needFlush;
   17.64 +  int needInitState;
   17.65 +  UInt32 numProbs;
   17.66 +  unsigned tempBufSize;
   17.67 +  Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
   17.68 +} CLzmaDec;
   17.69 +
   17.70 +#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
   17.71 +
   17.72 +void LzmaDec_Init(CLzmaDec *p);
   17.73 +
   17.74 +/* There are two types of LZMA streams:
   17.75 +     0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
   17.76 +     1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
   17.77 +
   17.78 +typedef enum
   17.79 +{
   17.80 +  LZMA_FINISH_ANY,   /* finish at any point */
   17.81 +  LZMA_FINISH_END    /* block must be finished at the end */
   17.82 +} ELzmaFinishMode;
   17.83 +
   17.84 +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
   17.85 +
   17.86 +   You must use LZMA_FINISH_END, when you know that current output buffer
   17.87 +   covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
   17.88 +
   17.89 +   If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
   17.90 +   and output value of destLen will be less than output buffer size limit.
   17.91 +   You can check status result also.
   17.92 +
   17.93 +   You can use multiple checks to test data integrity after full decompression:
   17.94 +     1) Check Result and "status" variable.
   17.95 +     2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
   17.96 +     3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
   17.97 +        You must use correct finish mode in that case. */
   17.98 +
   17.99 +typedef enum
  17.100 +{
  17.101 +  LZMA_STATUS_NOT_SPECIFIED,               /* use main error code instead */
  17.102 +  LZMA_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */
  17.103 +  LZMA_STATUS_NOT_FINISHED,                /* stream was not finished */
  17.104 +  LZMA_STATUS_NEEDS_MORE_INPUT,            /* you must provide more input bytes */
  17.105 +  LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK  /* there is probability that stream was finished without end mark */
  17.106 +} ELzmaStatus;
  17.107 +
  17.108 +/* ELzmaStatus is used only as output value for function call */
  17.109 +
  17.110 +
  17.111 +/* ---------- Interfaces ---------- */
  17.112 +
  17.113 +/* There are 3 levels of interfaces:
  17.114 +     1) Dictionary Interface
  17.115 +     2) Buffer Interface
  17.116 +     3) One Call Interface
  17.117 +   You can select any of these interfaces, but don't mix functions from different
  17.118 +   groups for same object. */
  17.119 +
  17.120 +
  17.121 +/* There are two variants to allocate state for Dictionary Interface:
  17.122 +     1) LzmaDec_Allocate / LzmaDec_Free
  17.123 +     2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
  17.124 +   You can use variant 2, if you set dictionary buffer manually.
  17.125 +   For Buffer Interface you must always use variant 1.
  17.126 +
  17.127 +LzmaDec_Allocate* can return:
  17.128 +  SZ_OK
  17.129 +  SZ_ERROR_MEM         - Memory allocation error
  17.130 +  SZ_ERROR_UNSUPPORTED - Unsupported properties
  17.131 +*/
  17.132 +   
  17.133 +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
  17.134 +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
  17.135 +
  17.136 +SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
  17.137 +void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
  17.138 +
  17.139 +/* ---------- Dictionary Interface ---------- */
  17.140 +
  17.141 +/* You can use it, if you want to eliminate the overhead for data copying from
  17.142 +   dictionary to some other external buffer.
  17.143 +   You must work with CLzmaDec variables directly in this interface.
  17.144 +
  17.145 +   STEPS:
  17.146 +     LzmaDec_Constr()
  17.147 +     LzmaDec_Allocate()
  17.148 +     for (each new stream)
  17.149 +     {
  17.150 +       LzmaDec_Init()
  17.151 +       while (it needs more decompression)
  17.152 +       {
  17.153 +         LzmaDec_DecodeToDic()
  17.154 +         use data from CLzmaDec::dic and update CLzmaDec::dicPos
  17.155 +       }
  17.156 +     }
  17.157 +     LzmaDec_Free()
  17.158 +*/
  17.159 +
  17.160 +/* LzmaDec_DecodeToDic
  17.161 +   
  17.162 +   The decoding to internal dictionary buffer (CLzmaDec::dic).
  17.163 +   You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
  17.164 +
  17.165 +finishMode:
  17.166 +  It has meaning only if the decoding reaches output limit (dicLimit).
  17.167 +  LZMA_FINISH_ANY - Decode just dicLimit bytes.
  17.168 +  LZMA_FINISH_END - Stream must be finished after dicLimit.
  17.169 +
  17.170 +Returns:
  17.171 +  SZ_OK
  17.172 +    status:
  17.173 +      LZMA_STATUS_FINISHED_WITH_MARK
  17.174 +      LZMA_STATUS_NOT_FINISHED
  17.175 +      LZMA_STATUS_NEEDS_MORE_INPUT
  17.176 +      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
  17.177 +  SZ_ERROR_DATA - Data error
  17.178 +*/
  17.179 +
  17.180 +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
  17.181 +    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
  17.182 +
  17.183 +
  17.184 +/* ---------- Buffer Interface ---------- */
  17.185 +
  17.186 +/* It's zlib-like interface.
  17.187 +   See LzmaDec_DecodeToDic description for information about STEPS and return results,
  17.188 +   but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
  17.189 +   to work with CLzmaDec variables manually.
  17.190 +
  17.191 +finishMode:
  17.192 +  It has meaning only if the decoding reaches output limit (*destLen).
  17.193 +  LZMA_FINISH_ANY - Decode just destLen bytes.
  17.194 +  LZMA_FINISH_END - Stream must be finished after (*destLen).
  17.195 +*/
  17.196 +
  17.197 +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
  17.198 +    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
  17.199 +
  17.200 +
  17.201 +/* ---------- One Call Interface ---------- */
  17.202 +
  17.203 +/* LzmaDecode
  17.204 +
  17.205 +finishMode:
  17.206 +  It has meaning only if the decoding reaches output limit (*destLen).
  17.207 +  LZMA_FINISH_ANY - Decode just destLen bytes.
  17.208 +  LZMA_FINISH_END - Stream must be finished after (*destLen).
  17.209 +
  17.210 +Returns:
  17.211 +  SZ_OK
  17.212 +    status:
  17.213 +      LZMA_STATUS_FINISHED_WITH_MARK
  17.214 +      LZMA_STATUS_NOT_FINISHED
  17.215 +      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
  17.216 +  SZ_ERROR_DATA - Data error
  17.217 +  SZ_ERROR_MEM  - Memory allocation error
  17.218 +  SZ_ERROR_UNSUPPORTED - Unsupported properties
  17.219 +  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
  17.220 +*/
  17.221 +
  17.222 +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
  17.223 +    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
  17.224 +    ELzmaStatus *status, ISzAlloc *alloc);
  17.225 +
  17.226 +#endif
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/libs/openctm/liblzma/LzmaEnc.c	Thu Sep 26 04:47:05 2013 +0300
    18.3 @@ -0,0 +1,2281 @@
    18.4 +/* LzmaEnc.c -- LZMA Encoder
    18.5 +2009-02-02 : Igor Pavlov : Public domain */
    18.6 +
    18.7 +#include <string.h>
    18.8 +
    18.9 +/* #define SHOW_STAT */
   18.10 +/* #define SHOW_STAT2 */
   18.11 +
   18.12 +#if defined(SHOW_STAT) || defined(SHOW_STAT2)
   18.13 +#include <stdio.h>
   18.14 +#endif
   18.15 +
   18.16 +#include "LzmaEnc.h"
   18.17 +
   18.18 +#include "LzFind.h"
   18.19 +#ifdef COMPRESS_MF_MT
   18.20 +#include "LzFindMt.h"
   18.21 +#endif
   18.22 +
   18.23 +#ifdef SHOW_STAT
   18.24 +static int ttt = 0;
   18.25 +#endif
   18.26 +
   18.27 +#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
   18.28 +
   18.29 +#define kBlockSize (9 << 10)
   18.30 +#define kUnpackBlockSize (1 << 18)
   18.31 +#define kMatchArraySize (1 << 21)
   18.32 +#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
   18.33 +
   18.34 +#define kNumMaxDirectBits (31)
   18.35 +
   18.36 +#define kNumTopBits 24
   18.37 +#define kTopValue ((UInt32)1 << kNumTopBits)
   18.38 +
   18.39 +#define kNumBitModelTotalBits 11
   18.40 +#define kBitModelTotal (1 << kNumBitModelTotalBits)
   18.41 +#define kNumMoveBits 5
   18.42 +#define kProbInitValue (kBitModelTotal >> 1)
   18.43 +
   18.44 +#define kNumMoveReducingBits 4
   18.45 +#define kNumBitPriceShiftBits 4
   18.46 +#define kBitPrice (1 << kNumBitPriceShiftBits)
   18.47 +
   18.48 +void LzmaEncProps_Init(CLzmaEncProps *p)
   18.49 +{
   18.50 +  p->level = 5;
   18.51 +  p->dictSize = p->mc = 0;
   18.52 +  p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
   18.53 +  p->writeEndMark = 0;
   18.54 +}
   18.55 +
   18.56 +void LzmaEncProps_Normalize(CLzmaEncProps *p)
   18.57 +{
   18.58 +  int level = p->level;
   18.59 +  if (level < 0) level = 5;
   18.60 +  p->level = level;
   18.61 +  if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
   18.62 +  if (p->lc < 0) p->lc = 3;
   18.63 +  if (p->lp < 0) p->lp = 0;
   18.64 +  if (p->pb < 0) p->pb = 2;
   18.65 +  if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
   18.66 +  if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
   18.67 +  if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
   18.68 +  if (p->numHashBytes < 0) p->numHashBytes = 4;
   18.69 +  if (p->mc == 0)  p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
   18.70 +  if (p->numThreads < 0)
   18.71 +    p->numThreads =
   18.72 +      #ifdef COMPRESS_MF_MT
   18.73 +      ((p->btMode && p->algo) ? 2 : 1);
   18.74 +      #else
   18.75 +      1;
   18.76 +      #endif
   18.77 +}
   18.78 +
   18.79 +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
   18.80 +{
   18.81 +  CLzmaEncProps props = *props2;
   18.82 +  LzmaEncProps_Normalize(&props);
   18.83 +  return props.dictSize;
   18.84 +}
   18.85 +
   18.86 +/* #define LZMA_LOG_BSR */
   18.87 +/* Define it for Intel's CPU */
   18.88 +
   18.89 +
   18.90 +#ifdef LZMA_LOG_BSR
   18.91 +
   18.92 +#define kDicLogSizeMaxCompress 30
   18.93 +
   18.94 +#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
   18.95 +
   18.96 +static UInt32 GetPosSlot1(UInt32 pos)
   18.97 +{
   18.98 +  UInt32 res;
   18.99 +  BSR2_RET(pos, res);
  18.100 +  return res;
  18.101 +}
  18.102 +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
  18.103 +#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
  18.104 +
  18.105 +#else
  18.106 +
  18.107 +#define kNumLogBits (9 + (int)sizeof(size_t) / 2)
  18.108 +#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
  18.109 +
  18.110 +void LzmaEnc_FastPosInit(Byte *g_FastPos)
  18.111 +{
  18.112 +  int c = 2, slotFast;
  18.113 +  g_FastPos[0] = 0;
  18.114 +  g_FastPos[1] = 1;
  18.115 +  
  18.116 +  for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
  18.117 +  {
  18.118 +    UInt32 k = (1 << ((slotFast >> 1) - 1));
  18.119 +    UInt32 j;
  18.120 +    for (j = 0; j < k; j++, c++)
  18.121 +      g_FastPos[c] = (Byte)slotFast;
  18.122 +  }
  18.123 +}
  18.124 +
  18.125 +#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
  18.126 +  (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
  18.127 +  res = p->g_FastPos[pos >> i] + (i * 2); }
  18.128 +/*
  18.129 +#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
  18.130 +  p->g_FastPos[pos >> 6] + 12 : \
  18.131 +  p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
  18.132 +*/
  18.133 +
  18.134 +#define GetPosSlot1(pos) p->g_FastPos[pos]
  18.135 +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
  18.136 +#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }
  18.137 +
  18.138 +#endif
  18.139 +
  18.140 +
  18.141 +#define LZMA_NUM_REPS 4
  18.142 +
  18.143 +typedef unsigned CState;
  18.144 +
  18.145 +typedef struct _COptimal
  18.146 +{
  18.147 +  UInt32 price;
  18.148 +
  18.149 +  CState state;
  18.150 +  int prev1IsChar;
  18.151 +  int prev2;
  18.152 +
  18.153 +  UInt32 posPrev2;
  18.154 +  UInt32 backPrev2;
  18.155 +
  18.156 +  UInt32 posPrev;
  18.157 +  UInt32 backPrev;
  18.158 +  UInt32 backs[LZMA_NUM_REPS];
  18.159 +} COptimal;
  18.160 +
  18.161 +#define kNumOpts (1 << 12)
  18.162 +
  18.163 +#define kNumLenToPosStates 4
  18.164 +#define kNumPosSlotBits 6
  18.165 +#define kDicLogSizeMin 0
  18.166 +#define kDicLogSizeMax 32
  18.167 +#define kDistTableSizeMax (kDicLogSizeMax * 2)
  18.168 +
  18.169 +
  18.170 +#define kNumAlignBits 4
  18.171 +#define kAlignTableSize (1 << kNumAlignBits)
  18.172 +#define kAlignMask (kAlignTableSize - 1)
  18.173 +
  18.174 +#define kStartPosModelIndex 4
  18.175 +#define kEndPosModelIndex 14
  18.176 +#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
  18.177 +
  18.178 +#define kNumFullDistances (1 << (kEndPosModelIndex / 2))
  18.179 +
  18.180 +#ifdef _LZMA_PROB32
  18.181 +#define CLzmaProb UInt32
  18.182 +#else
  18.183 +#define CLzmaProb UInt16
  18.184 +#endif
  18.185 +
  18.186 +#define LZMA_PB_MAX 4
  18.187 +#define LZMA_LC_MAX 8
  18.188 +#define LZMA_LP_MAX 4
  18.189 +
  18.190 +#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
  18.191 +
  18.192 +
  18.193 +#define kLenNumLowBits 3
  18.194 +#define kLenNumLowSymbols (1 << kLenNumLowBits)
  18.195 +#define kLenNumMidBits 3
  18.196 +#define kLenNumMidSymbols (1 << kLenNumMidBits)
  18.197 +#define kLenNumHighBits 8
  18.198 +#define kLenNumHighSymbols (1 << kLenNumHighBits)
  18.199 +
  18.200 +#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
  18.201 +
  18.202 +#define LZMA_MATCH_LEN_MIN 2
  18.203 +#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
  18.204 +
  18.205 +#define kNumStates 12
  18.206 +
  18.207 +typedef struct
  18.208 +{
  18.209 +  CLzmaProb choice;
  18.210 +  CLzmaProb choice2;
  18.211 +  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];
  18.212 +  CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];
  18.213 +  CLzmaProb high[kLenNumHighSymbols];
  18.214 +} CLenEnc;
  18.215 +
  18.216 +typedef struct
  18.217 +{
  18.218 +  CLenEnc p;
  18.219 +  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
  18.220 +  UInt32 tableSize;
  18.221 +  UInt32 counters[LZMA_NUM_PB_STATES_MAX];
  18.222 +} CLenPriceEnc;
  18.223 +
  18.224 +typedef struct _CRangeEnc
  18.225 +{
  18.226 +  UInt32 range;
  18.227 +  Byte cache;
  18.228 +  UInt64 low;
  18.229 +  UInt64 cacheSize;
  18.230 +  Byte *buf;
  18.231 +  Byte *bufLim;
  18.232 +  Byte *bufBase;
  18.233 +  ISeqOutStream *outStream;
  18.234 +  UInt64 processed;
  18.235 +  SRes res;
  18.236 +} CRangeEnc;
  18.237 +
  18.238 +typedef struct _CSeqInStreamBuf
  18.239 +{
  18.240 +  ISeqInStream funcTable;
  18.241 +  const Byte *data;
  18.242 +  SizeT rem;
  18.243 +} CSeqInStreamBuf;
  18.244 +
  18.245 +static SRes MyRead(void *pp, void *data, size_t *size)
  18.246 +{
  18.247 +  size_t curSize = *size;
  18.248 +  CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp;
  18.249 +  if (p->rem < curSize)
  18.250 +    curSize = p->rem;
  18.251 +  memcpy(data, p->data, curSize);
  18.252 +  p->rem -= curSize;
  18.253 +  p->data += curSize;
  18.254 +  *size = curSize;
  18.255 +  return SZ_OK;
  18.256 +}
  18.257 +
  18.258 +typedef struct
  18.259 +{
  18.260 +  CLzmaProb *litProbs;
  18.261 +
  18.262 +  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
  18.263 +  CLzmaProb isRep[kNumStates];
  18.264 +  CLzmaProb isRepG0[kNumStates];
  18.265 +  CLzmaProb isRepG1[kNumStates];
  18.266 +  CLzmaProb isRepG2[kNumStates];
  18.267 +  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
  18.268 +
  18.269 +  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
  18.270 +  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
  18.271 +  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
  18.272 +  
  18.273 +  CLenPriceEnc lenEnc;
  18.274 +  CLenPriceEnc repLenEnc;
  18.275 +
  18.276 +  UInt32 reps[LZMA_NUM_REPS];
  18.277 +  UInt32 state;
  18.278 +} CSaveState;
  18.279 +
  18.280 +typedef struct _CLzmaEnc
  18.281 +{
  18.282 +  IMatchFinder matchFinder;
  18.283 +  void *matchFinderObj;
  18.284 +
  18.285 +  #ifdef COMPRESS_MF_MT
  18.286 +  Bool mtMode;
  18.287 +  CMatchFinderMt matchFinderMt;
  18.288 +  #endif
  18.289 +
  18.290 +  CMatchFinder matchFinderBase;
  18.291 +
  18.292 +  #ifdef COMPRESS_MF_MT
  18.293 +  Byte pad[128];
  18.294 +  #endif
  18.295 +  
  18.296 +  UInt32 optimumEndIndex;
  18.297 +  UInt32 optimumCurrentIndex;
  18.298 +
  18.299 +  UInt32 longestMatchLength;
  18.300 +  UInt32 numPairs;
  18.301 +  UInt32 numAvail;
  18.302 +  COptimal opt[kNumOpts];
  18.303 +  
  18.304 +  #ifndef LZMA_LOG_BSR
  18.305 +  Byte g_FastPos[1 << kNumLogBits];
  18.306 +  #endif
  18.307 +
  18.308 +  UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
  18.309 +  UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
  18.310 +  UInt32 numFastBytes;
  18.311 +  UInt32 additionalOffset;
  18.312 +  UInt32 reps[LZMA_NUM_REPS];
  18.313 +  UInt32 state;
  18.314 +
  18.315 +  UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
  18.316 +  UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
  18.317 +  UInt32 alignPrices[kAlignTableSize];
  18.318 +  UInt32 alignPriceCount;
  18.319 +
  18.320 +  UInt32 distTableSize;
  18.321 +
  18.322 +  unsigned lc, lp, pb;
  18.323 +  unsigned lpMask, pbMask;
  18.324 +
  18.325 +  CLzmaProb *litProbs;
  18.326 +
  18.327 +  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
  18.328 +  CLzmaProb isRep[kNumStates];
  18.329 +  CLzmaProb isRepG0[kNumStates];
  18.330 +  CLzmaProb isRepG1[kNumStates];
  18.331 +  CLzmaProb isRepG2[kNumStates];
  18.332 +  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
  18.333 +
  18.334 +  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
  18.335 +  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
  18.336 +  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
  18.337 +  
  18.338 +  CLenPriceEnc lenEnc;
  18.339 +  CLenPriceEnc repLenEnc;
  18.340 +
  18.341 +  unsigned lclp;
  18.342 +
  18.343 +  Bool fastMode;
  18.344 +  
  18.345 +  CRangeEnc rc;
  18.346 +
  18.347 +  Bool writeEndMark;
  18.348 +  UInt64 nowPos64;
  18.349 +  UInt32 matchPriceCount;
  18.350 +  Bool finished;
  18.351 +  Bool multiThread;
  18.352 +
  18.353 +  SRes result;
  18.354 +  UInt32 dictSize;
  18.355 +  UInt32 matchFinderCycles;
  18.356 +
  18.357 +  ISeqInStream *inStream;
  18.358 +  CSeqInStreamBuf seqBufInStream;
  18.359 +
  18.360 +  CSaveState saveState;
  18.361 +} CLzmaEnc;
  18.362 +
  18.363 +void LzmaEnc_SaveState(CLzmaEncHandle pp)
  18.364 +{
  18.365 +  CLzmaEnc *p = (CLzmaEnc *)pp;
  18.366 +  CSaveState *dest = &p->saveState;
  18.367 +  int i;
  18.368 +  dest->lenEnc = p->lenEnc;
  18.369 +  dest->repLenEnc = p->repLenEnc;
  18.370 +  dest->state = p->state;
  18.371 +
  18.372 +  for (i = 0; i < kNumStates; i++)
  18.373 +  {
  18.374 +    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
  18.375 +    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
  18.376 +  }
  18.377 +  for (i = 0; i < kNumLenToPosStates; i++)
  18.378 +    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
  18.379 +  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
  18.380 +  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
  18.381 +  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
  18.382 +  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
  18.383 +  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
  18.384 +  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
  18.385 +  memcpy(dest->reps, p->reps, sizeof(p->reps));
  18.386 +  memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
  18.387 +}
  18.388 +
  18.389 +void LzmaEnc_RestoreState(CLzmaEncHandle pp)
  18.390 +{
  18.391 +  CLzmaEnc *dest = (CLzmaEnc *)pp;
  18.392 +  const CSaveState *p = &dest->saveState;
  18.393 +  int i;
  18.394 +  dest->lenEnc = p->lenEnc;
  18.395 +  dest->repLenEnc = p->repLenEnc;
  18.396 +  dest->state = p->state;
  18.397 +
  18.398 +  for (i = 0; i < kNumStates; i++)
  18.399 +  {
  18.400 +    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
  18.401 +    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
  18.402 +  }
  18.403 +  for (i = 0; i < kNumLenToPosStates; i++)
  18.404 +    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
  18.405 +  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
  18.406 +  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
  18.407 +  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
  18.408 +  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
  18.409 +  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
  18.410 +  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
  18.411 +  memcpy(dest->reps, p->reps, sizeof(p->reps));
  18.412 +  memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
  18.413 +}
  18.414 +
  18.415 +SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
  18.416 +{
  18.417 +  CLzmaEnc *p = (CLzmaEnc *)pp;
  18.418 +  CLzmaEncProps props = *props2;
  18.419 +  LzmaEncProps_Normalize(&props);
  18.420 +
  18.421 +  if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||
  18.422 +      props.dictSize > (1U << kDicLogSizeMaxCompress) || props.dictSize > (1U << 30))
  18.423 +    return SZ_ERROR_PARAM;
  18.424 +  p->dictSize = props.dictSize;
  18.425 +  p->matchFinderCycles = props.mc;
  18.426 +  {
  18.427 +    unsigned fb = props.fb;
  18.428 +    if (fb < 5)
  18.429 +      fb = 5;
  18.430 +    if (fb > LZMA_MATCH_LEN_MAX)
  18.431 +      fb = LZMA_MATCH_LEN_MAX;
  18.432 +    p->numFastBytes = fb;
  18.433 +  }
  18.434 +  p->lc = props.lc;
  18.435 +  p->lp = props.lp;
  18.436 +  p->pb = props.pb;
  18.437 +  p->fastMode = (props.algo == 0);
  18.438 +  p->matchFinderBase.btMode = props.btMode;
  18.439 +  {
  18.440 +    UInt32 numHashBytes = 4;
  18.441 +    if (props.btMode)
  18.442 +    {
  18.443 +      if (props.numHashBytes < 2)
  18.444 +        numHashBytes = 2;
  18.445 +      else if (props.numHashBytes < 4)
  18.446 +        numHashBytes = props.numHashBytes;
  18.447 +    }
  18.448 +    p->matchFinderBase.numHashBytes = numHashBytes;
  18.449 +  }
  18.450 +
  18.451 +  p->matchFinderBase.cutValue = props.mc;
  18.452 +
  18.453 +  p->writeEndMark = props.writeEndMark;
  18.454 +
  18.455 +  #ifdef COMPRESS_MF_MT
  18.456 +  /*
  18.457 +  if (newMultiThread != _multiThread)
  18.458 +  {
  18.459 +    ReleaseMatchFinder();
  18.460 +    _multiThread = newMultiThread;
  18.461 +  }
  18.462 +  */
  18.463 +  p->multiThread = (props.numThreads > 1);
  18.464 +  #endif
  18.465 +
  18.466 +  return SZ_OK;
  18.467 +}
  18.468 +
  18.469 +static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
  18.470 +static const int kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
  18.471 +static const int kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
  18.472 +static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
  18.473 +
  18.474 +#define IsCharState(s) ((s) < 7)
  18.475 +
  18.476 +#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
  18.477 +
  18.478 +#define kInfinityPrice (1 << 30)
  18.479 +
  18.480 +static void RangeEnc_Construct(CRangeEnc *p)
  18.481 +{
  18.482 +  p->outStream = 0;
  18.483 +  p->bufBase = 0;
  18.484 +}
  18.485 +
  18.486 +#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
  18.487 +
  18.488 +#define RC_BUF_SIZE (1 << 16)
  18.489 +static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
  18.490 +{
  18.491 +  if (p->bufBase == 0)
  18.492 +  {
  18.493 +    p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
  18.494 +    if (p->bufBase == 0)
  18.495 +      return 0;
  18.496 +    p->bufLim = p->bufBase + RC_BUF_SIZE;
  18.497 +  }
  18.498 +  return 1;
  18.499 +}
  18.500 +
  18.501 +static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
  18.502 +{
  18.503 +  alloc->Free(alloc, p->bufBase);
  18.504 +  p->bufBase = 0;
  18.505 +}
  18.506 +
  18.507 +static void RangeEnc_Init(CRangeEnc *p)
  18.508 +{
  18.509 +  /* Stream.Init(); */
  18.510 +  p->low = 0;
  18.511 +  p->range = 0xFFFFFFFF;
  18.512 +  p->cacheSize = 1;
  18.513 +  p->cache = 0;
  18.514 +
  18.515 +  p->buf = p->bufBase;
  18.516 +
  18.517 +  p->processed = 0;
  18.518 +  p->res = SZ_OK;
  18.519 +}
  18.520 +
  18.521 +static void RangeEnc_FlushStream(CRangeEnc *p)
  18.522 +{
  18.523 +  size_t num;
  18.524 +  if (p->res != SZ_OK)
  18.525 +    return;
  18.526 +  num = p->buf - p->bufBase;
  18.527 +  if (num != p->outStream->Write(p->outStream, p->bufBase, num))
  18.528 +    p->res = SZ_ERROR_WRITE;
  18.529 +  p->processed += num;
  18.530 +  p->buf = p->bufBase;
  18.531 +}
  18.532 +
  18.533 +static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
  18.534 +{
  18.535 +  if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)
  18.536 +  {
  18.537 +    Byte temp = p->cache;
  18.538 +    do
  18.539 +    {
  18.540 +      Byte *buf = p->buf;
  18.541 +      *buf++ = (Byte)(temp + (Byte)(p->low >> 32));
  18.542 +      p->buf = buf;
  18.543 +      if (buf == p->bufLim)
  18.544 +        RangeEnc_FlushStream(p);
  18.545 +      temp = 0xFF;
  18.546 +    }
  18.547 +    while (--p->cacheSize != 0);
  18.548 +    p->cache = (Byte)((UInt32)p->low >> 24);
  18.549 +  }
  18.550 +  p->cacheSize++;
  18.551 +  p->low = (UInt32)p->low << 8;
  18.552 +}
  18.553 +
  18.554 +static void RangeEnc_FlushData(CRangeEnc *p)
  18.555 +{
  18.556 +  int i;
  18.557 +  for (i = 0; i < 5; i++)
  18.558 +    RangeEnc_ShiftLow(p);
  18.559 +}
  18.560 +
  18.561 +static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)
  18.562 +{
  18.563 +  do
  18.564 +  {
  18.565 +    p->range >>= 1;
  18.566 +    p->low += p->range & (0 - ((value >> --numBits) & 1));
  18.567 +    if (p->range < kTopValue)
  18.568 +    {
  18.569 +      p->range <<= 8;
  18.570 +      RangeEnc_ShiftLow(p);
  18.571 +    }
  18.572 +  }
  18.573 +  while (numBits != 0);
  18.574 +}
  18.575 +
  18.576 +static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
  18.577 +{
  18.578 +  UInt32 ttt = *prob;
  18.579 +  UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;
  18.580 +  if (symbol == 0)
  18.581 +  {
  18.582 +    p->range = newBound;
  18.583 +    ttt += (kBitModelTotal - ttt) >> kNumMoveBits;
  18.584 +  }
  18.585 +  else
  18.586 +  {
  18.587 +    p->low += newBound;
  18.588 +    p->range -= newBound;
  18.589 +    ttt -= ttt >> kNumMoveBits;
  18.590 +  }
  18.591 +  *prob = (CLzmaProb)ttt;
  18.592 +  if (p->range < kTopValue)
  18.593 +  {
  18.594 +    p->range <<= 8;
  18.595 +    RangeEnc_ShiftLow(p);
  18.596 +  }
  18.597 +}
  18.598 +
  18.599 +static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
  18.600 +{
  18.601 +  symbol |= 0x100;
  18.602 +  do
  18.603 +  {
  18.604 +    RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
  18.605 +    symbol <<= 1;
  18.606 +  }
  18.607 +  while (symbol < 0x10000);
  18.608 +}
  18.609 +
  18.610 +static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
  18.611 +{
  18.612 +  UInt32 offs = 0x100;
  18.613 +  symbol |= 0x100;
  18.614 +  do
  18.615 +  {
  18.616 +    matchByte <<= 1;
  18.617 +    RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
  18.618 +    symbol <<= 1;
  18.619 +    offs &= ~(matchByte ^ symbol);
  18.620 +  }
  18.621 +  while (symbol < 0x10000);
  18.622 +}
  18.623 +
  18.624 +void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
  18.625 +{
  18.626 +  UInt32 i;
  18.627 +  for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
  18.628 +  {
  18.629 +    const int kCyclesBits = kNumBitPriceShiftBits;
  18.630 +    UInt32 w = i;
  18.631 +    UInt32 bitCount = 0;
  18.632 +    int j;
  18.633 +    for (j = 0; j < kCyclesBits; j++)
  18.634 +    {
  18.635 +      w = w * w;
  18.636 +      bitCount <<= 1;
  18.637 +      while (w >= ((UInt32)1 << 16))
  18.638 +      {
  18.639 +        w >>= 1;
  18.640 +        bitCount++;
  18.641 +      }
  18.642 +    }
  18.643 +    ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
  18.644 +  }
  18.645 +}
  18.646 +
  18.647 +
  18.648 +#define GET_PRICE(prob, symbol) \
  18.649 +  p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
  18.650 +
  18.651 +#define GET_PRICEa(prob, symbol) \
  18.652 +  ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
  18.653 +
  18.654 +#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
  18.655 +#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
  18.656 +
  18.657 +#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
  18.658 +#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
  18.659 +
  18.660 +static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
  18.661 +{
  18.662 +  UInt32 price = 0;
  18.663 +  symbol |= 0x100;
  18.664 +  do
  18.665 +  {
  18.666 +    price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);
  18.667 +    symbol <<= 1;
  18.668 +  }
  18.669 +  while (symbol < 0x10000);
  18.670 +  return price;
  18.671 +}
  18.672 +
  18.673 +static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
  18.674 +{
  18.675 +  UInt32 price = 0;
  18.676 +  UInt32 offs = 0x100;
  18.677 +  symbol |= 0x100;
  18.678 +  do
  18.679 +  {
  18.680 +    matchByte <<= 1;
  18.681 +    price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
  18.682 +    symbol <<= 1;
  18.683 +    offs &= ~(matchByte ^ symbol);
  18.684 +  }
  18.685 +  while (symbol < 0x10000);
  18.686 +  return price;
  18.687 +}
  18.688 +
  18.689 +
  18.690 +static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
  18.691 +{
  18.692 +  UInt32 m = 1;
  18.693 +  int i;
  18.694 +  for (i = numBitLevels; i != 0;)
  18.695 +  {
  18.696 +    UInt32 bit;
  18.697 +    i--;
  18.698 +    bit = (symbol >> i) & 1;
  18.699 +    RangeEnc_EncodeBit(rc, probs + m, bit);
  18.700 +    m = (m << 1) | bit;
  18.701 +  }
  18.702 +}
  18.703 +
  18.704 +static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
  18.705 +{
  18.706 +  UInt32 m = 1;
  18.707 +  int i;
  18.708 +  for (i = 0; i < numBitLevels; i++)
  18.709 +  {
  18.710 +    UInt32 bit = symbol & 1;
  18.711 +    RangeEnc_EncodeBit(rc, probs + m, bit);
  18.712 +    m = (m << 1) | bit;
  18.713 +    symbol >>= 1;
  18.714 +  }
  18.715 +}
  18.716 +
  18.717 +static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
  18.718 +{
  18.719 +  UInt32 price = 0;
  18.720 +  symbol |= (1 << numBitLevels);
  18.721 +  while (symbol != 1)
  18.722 +  {
  18.723 +    price += GET_PRICEa(probs[symbol >> 1], symbol & 1);
  18.724 +    symbol >>= 1;
  18.725 +  }
  18.726 +  return price;
  18.727 +}
  18.728 +
  18.729 +static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
  18.730 +{
  18.731 +  UInt32 price = 0;
  18.732 +  UInt32 m = 1;
  18.733 +  int i;
  18.734 +  for (i = numBitLevels; i != 0; i--)
  18.735 +  {
  18.736 +    UInt32 bit = symbol & 1;
  18.737 +    symbol >>= 1;
  18.738 +    price += GET_PRICEa(probs[m], bit);
  18.739 +    m = (m << 1) | bit;
  18.740 +  }
  18.741 +  return price;
  18.742 +}
  18.743 +
  18.744 +
  18.745 +static void LenEnc_Init(CLenEnc *p)
  18.746 +{
  18.747 +  unsigned i;
  18.748 +  p->choice = p->choice2 = kProbInitValue;
  18.749 +  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)
  18.750 +    p->low[i] = kProbInitValue;
  18.751 +  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)
  18.752 +    p->mid[i] = kProbInitValue;
  18.753 +  for (i = 0; i < kLenNumHighSymbols; i++)
  18.754 +    p->high[i] = kProbInitValue;
  18.755 +}
  18.756 +
  18.757 +static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
  18.758 +{
  18.759 +  if (symbol < kLenNumLowSymbols)
  18.760 +  {
  18.761 +    RangeEnc_EncodeBit(rc, &p->choice, 0);
  18.762 +    RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
  18.763 +  }
  18.764 +  else
  18.765 +  {
  18.766 +    RangeEnc_EncodeBit(rc, &p->choice, 1);
  18.767 +    if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)
  18.768 +    {
  18.769 +      RangeEnc_EncodeBit(rc, &p->choice2, 0);
  18.770 +      RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
  18.771 +    }
  18.772 +    else
  18.773 +    {
  18.774 +      RangeEnc_EncodeBit(rc, &p->choice2, 1);
  18.775 +      RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
  18.776 +    }
  18.777 +  }
  18.778 +}
  18.779 +
  18.780 +static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
  18.781 +{
  18.782 +  UInt32 a0 = GET_PRICE_0a(p->choice);
  18.783 +  UInt32 a1 = GET_PRICE_1a(p->choice);
  18.784 +  UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);
  18.785 +  UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);
  18.786 +  UInt32 i = 0;
  18.787 +  for (i = 0; i < kLenNumLowSymbols; i++)
  18.788 +  {
  18.789 +    if (i >= numSymbols)
  18.790 +      return;
  18.791 +    prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
  18.792 +  }
  18.793 +  for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)
  18.794 +  {
  18.795 +    if (i >= numSymbols)
  18.796 +      return;
  18.797 +    prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
  18.798 +  }
  18.799 +  for (; i < numSymbols; i++)
  18.800 +    prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
  18.801 +}
  18.802 +
  18.803 +static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
  18.804 +{
  18.805 +  LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
  18.806 +  p->counters[posState] = p->tableSize;
  18.807 +}
  18.808 +
  18.809 +static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
  18.810 +{
  18.811 +  UInt32 posState;
  18.812 +  for (posState = 0; posState < numPosStates; posState++)
  18.813 +    LenPriceEnc_UpdateTable(p, posState, ProbPrices);
  18.814 +}
  18.815 +
  18.816 +static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
  18.817 +{
  18.818 +  LenEnc_Encode(&p->p, rc, symbol, posState);
  18.819 +  if (updatePrice)
  18.820 +    if (--p->counters[posState] == 0)
  18.821 +      LenPriceEnc_UpdateTable(p, posState, ProbPrices);
  18.822 +}
  18.823 +
  18.824 +
  18.825 +
  18.826 +
  18.827 +static void MovePos(CLzmaEnc *p, UInt32 num)
  18.828 +{
  18.829 +  #ifdef SHOW_STAT
  18.830 +  ttt += num;
  18.831 +  printf("\n MovePos %d", num);
  18.832 +  #endif
  18.833 +  if (num != 0)
  18.834 +  {
  18.835 +    p->additionalOffset += num;
  18.836 +    p->matchFinder.Skip(p->matchFinderObj, num);
  18.837 +  }
  18.838 +}
  18.839 +
  18.840 +static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
  18.841 +{
  18.842 +  UInt32 lenRes = 0, numPairs;
  18.843 +  p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
  18.844 +  numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
  18.845 +  #ifdef SHOW_STAT
  18.846 +  printf("\n i = %d numPairs = %d    ", ttt, numPairs / 2);
  18.847 +  ttt++;
  18.848 +  {
  18.849 +    UInt32 i;
  18.850 +    for (i = 0; i < numPairs; i += 2)
  18.851 +      printf("%2d %6d   | ", p->matches[i], p->matches[i + 1]);
  18.852 +  }
  18.853 +  #endif
  18.854 +  if (numPairs > 0)
  18.855 +  {
  18.856 +    lenRes = p->matches[numPairs - 2];
  18.857 +    if (lenRes == p->numFastBytes)
  18.858 +    {
  18.859 +      const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
  18.860 +      UInt32 distance = p->matches[numPairs - 1] + 1;
  18.861 +      UInt32 numAvail = p->numAvail;
  18.862 +      if (numAvail > LZMA_MATCH_LEN_MAX)
  18.863 +        numAvail = LZMA_MATCH_LEN_MAX;
  18.864 +      {
  18.865 +        const Byte *pby2 = pby - distance;
  18.866 +        for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
  18.867 +      }
  18.868 +    }
  18.869 +  }
  18.870 +  p->additionalOffset++;
  18.871 +  *numDistancePairsRes = numPairs;
  18.872 +  return lenRes;
  18.873 +}
  18.874 +
  18.875 +
  18.876 +#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;
  18.877 +#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;
  18.878 +#define IsShortRep(p) ((p)->backPrev == 0)
  18.879 +
  18.880 +static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
  18.881 +{
  18.882 +  return
  18.883 +    GET_PRICE_0(p->isRepG0[state]) +
  18.884 +    GET_PRICE_0(p->isRep0Long[state][posState]);
  18.885 +}
  18.886 +
  18.887 +static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
  18.888 +{
  18.889 +  UInt32 price;
  18.890 +  if (repIndex == 0)
  18.891 +  {
  18.892 +    price = GET_PRICE_0(p->isRepG0[state]);
  18.893 +    price += GET_PRICE_1(p->isRep0Long[state][posState]);
  18.894 +  }
  18.895 +  else
  18.896 +  {
  18.897 +    price = GET_PRICE_1(p->isRepG0[state]);
  18.898 +    if (repIndex == 1)
  18.899 +      price += GET_PRICE_0(p->isRepG1[state]);
  18.900 +    else
  18.901 +    {
  18.902 +      price += GET_PRICE_1(p->isRepG1[state]);
  18.903 +      price += GET_PRICE(p->isRepG2[state], repIndex - 2);
  18.904 +    }
  18.905 +  }
  18.906 +  return price;
  18.907 +}
  18.908 +
  18.909 +static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
  18.910 +{
  18.911 +  return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
  18.912 +    GetPureRepPrice(p, repIndex, state, posState);
  18.913 +}
  18.914 +
  18.915 +static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
  18.916 +{
  18.917 +  UInt32 posMem = p->opt[cur].posPrev;
  18.918 +  UInt32 backMem = p->opt[cur].backPrev;
  18.919 +  p->optimumEndIndex = cur;
  18.920 +  do
  18.921 +  {
  18.922 +    if (p->opt[cur].prev1IsChar)
  18.923 +    {
  18.924 +      MakeAsChar(&p->opt[posMem])
  18.925 +      p->opt[posMem].posPrev = posMem - 1;
  18.926 +      if (p->opt[cur].prev2)
  18.927 +      {
  18.928 +        p->opt[posMem - 1].prev1IsChar = False;
  18.929 +        p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
  18.930 +        p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
  18.931 +      }
  18.932 +    }
  18.933 +    {
  18.934 +      UInt32 posPrev = posMem;
  18.935 +      UInt32 backCur = backMem;
  18.936 +      
  18.937 +      backMem = p->opt[posPrev].backPrev;
  18.938 +      posMem = p->opt[posPrev].posPrev;
  18.939 +      
  18.940 +      p->opt[posPrev].backPrev = backCur;
  18.941 +      p->opt[posPrev].posPrev = cur;
  18.942 +      cur = posPrev;
  18.943 +    }
  18.944 +  }
  18.945 +  while (cur != 0);
  18.946 +  *backRes = p->opt[0].backPrev;
  18.947 +  p->optimumCurrentIndex  = p->opt[0].posPrev;
  18.948 +  return p->optimumCurrentIndex;
  18.949 +}
  18.950 +
  18.951 +#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
  18.952 +
  18.953 +static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
  18.954 +{
  18.955 +  UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;
  18.956 +  UInt32 matchPrice, repMatchPrice, normalMatchPrice;
  18.957 +  UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];
  18.958 +  UInt32 *matches;
  18.959 +  const Byte *data;
  18.960 +  Byte curByte, matchByte;
  18.961 +  if (p->optimumEndIndex != p->optimumCurrentIndex)
  18.962 +  {
  18.963 +    const COptimal *opt = &p->opt[p->optimumCurrentIndex];
  18.964 +    UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
  18.965 +    *backRes = opt->backPrev;
  18.966 +    p->optimumCurrentIndex = opt->posPrev;
  18.967 +    return lenRes;
  18.968 +  }
  18.969 +  p->optimumCurrentIndex = p->optimumEndIndex = 0;
  18.970 +  
  18.971 +  if (p->additionalOffset == 0)
  18.972 +    mainLen = ReadMatchDistances(p, &numPairs);
  18.973 +  else
  18.974 +  {
  18.975 +    mainLen = p->longestMatchLength;
  18.976 +    numPairs = p->numPairs;
  18.977 +  }
  18.978 +
  18.979 +  numAvail = p->numAvail;
  18.980 +  if (numAvail < 2)
  18.981 +  {
  18.982 +    *backRes = (UInt32)(-1);
  18.983 +    return 1;
  18.984 +  }
  18.985 +  if (numAvail > LZMA_MATCH_LEN_MAX)
  18.986 +    numAvail = LZMA_MATCH_LEN_MAX;
  18.987 +
  18.988 +  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
  18.989 +  repMaxIndex = 0;
  18.990 +  for (i = 0; i < LZMA_NUM_REPS; i++)
  18.991 +  {
  18.992 +    UInt32 lenTest;
  18.993 +    const Byte *data2;
  18.994 +    reps[i] = p->reps[i];
  18.995 +    data2 = data - (reps[i] + 1);
  18.996 +    if (data[0] != data2[0] || data[1] != data2[1])
  18.997 +    {
  18.998 +      repLens[i] = 0;
  18.999 +      continue;
 18.1000 +    }
 18.1001 +    for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
 18.1002 +    repLens[i] = lenTest;
 18.1003 +    if (lenTest > repLens[repMaxIndex])
 18.1004 +      repMaxIndex = i;
 18.1005 +  }
 18.1006 +  if (repLens[repMaxIndex] >= p->numFastBytes)
 18.1007 +  {
 18.1008 +    UInt32 lenRes;
 18.1009 +    *backRes = repMaxIndex;
 18.1010 +    lenRes = repLens[repMaxIndex];
 18.1011 +    MovePos(p, lenRes - 1);
 18.1012 +    return lenRes;
 18.1013 +  }
 18.1014 +
 18.1015 +  matches = p->matches;
 18.1016 +  if (mainLen >= p->numFastBytes)
 18.1017 +  {
 18.1018 +    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
 18.1019 +    MovePos(p, mainLen - 1);
 18.1020 +    return mainLen;
 18.1021 +  }
 18.1022 +  curByte = *data;
 18.1023 +  matchByte = *(data - (reps[0] + 1));
 18.1024 +
 18.1025 +  if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
 18.1026 +  {
 18.1027 +    *backRes = (UInt32)-1;
 18.1028 +    return 1;
 18.1029 +  }
 18.1030 +
 18.1031 +  p->opt[0].state = (CState)p->state;
 18.1032 +
 18.1033 +  posState = (position & p->pbMask);
 18.1034 +
 18.1035 +  {
 18.1036 +    const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
 18.1037 +    p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
 18.1038 +        (!IsCharState(p->state) ?
 18.1039 +          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
 18.1040 +          LitEnc_GetPrice(probs, curByte, p->ProbPrices));
 18.1041 +  }
 18.1042 +
 18.1043 +  MakeAsChar(&p->opt[1]);
 18.1044 +
 18.1045 +  matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
 18.1046 +  repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
 18.1047 +
 18.1048 +  if (matchByte == curByte)
 18.1049 +  {
 18.1050 +    UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
 18.1051 +    if (shortRepPrice < p->opt[1].price)
 18.1052 +    {
 18.1053 +      p->opt[1].price = shortRepPrice;
 18.1054 +      MakeAsShortRep(&p->opt[1]);
 18.1055 +    }
 18.1056 +  }
 18.1057 +  lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);
 18.1058 +
 18.1059 +  if (lenEnd < 2)
 18.1060 +  {
 18.1061 +    *backRes = p->opt[1].backPrev;
 18.1062 +    return 1;
 18.1063 +  }
 18.1064 +
 18.1065 +  p->opt[1].posPrev = 0;
 18.1066 +  for (i = 0; i < LZMA_NUM_REPS; i++)
 18.1067 +    p->opt[0].backs[i] = reps[i];
 18.1068 +
 18.1069 +  len = lenEnd;
 18.1070 +  do
 18.1071 +    p->opt[len--].price = kInfinityPrice;
 18.1072 +  while (len >= 2);
 18.1073 +
 18.1074 +  for (i = 0; i < LZMA_NUM_REPS; i++)
 18.1075 +  {
 18.1076 +    UInt32 repLen = repLens[i];
 18.1077 +    UInt32 price;
 18.1078 +    if (repLen < 2)
 18.1079 +      continue;
 18.1080 +    price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
 18.1081 +    do
 18.1082 +    {
 18.1083 +      UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
 18.1084 +      COptimal *opt = &p->opt[repLen];
 18.1085 +      if (curAndLenPrice < opt->price)
 18.1086 +      {
 18.1087 +        opt->price = curAndLenPrice;
 18.1088 +        opt->posPrev = 0;
 18.1089 +        opt->backPrev = i;
 18.1090 +        opt->prev1IsChar = False;
 18.1091 +      }
 18.1092 +    }
 18.1093 +    while (--repLen >= 2);
 18.1094 +  }
 18.1095 +
 18.1096 +  normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
 18.1097 +
 18.1098 +  len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
 18.1099 +  if (len <= mainLen)
 18.1100 +  {
 18.1101 +    UInt32 offs = 0;
 18.1102 +    while (len > matches[offs])
 18.1103 +      offs += 2;
 18.1104 +    for (; ; len++)
 18.1105 +    {
 18.1106 +      COptimal *opt;
 18.1107 +      UInt32 distance = matches[offs + 1];
 18.1108 +
 18.1109 +      UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
 18.1110 +      UInt32 lenToPosState = GetLenToPosState(len);
 18.1111 +      if (distance < kNumFullDistances)
 18.1112 +        curAndLenPrice += p->distancesPrices[lenToPosState][distance];
 18.1113 +      else
 18.1114 +      {
 18.1115 +        UInt32 slot;
 18.1116 +        GetPosSlot2(distance, slot);
 18.1117 +        curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
 18.1118 +      }
 18.1119 +      opt = &p->opt[len];
 18.1120 +      if (curAndLenPrice < opt->price)
 18.1121 +      {
 18.1122 +        opt->price = curAndLenPrice;
 18.1123 +        opt->posPrev = 0;
 18.1124 +        opt->backPrev = distance + LZMA_NUM_REPS;
 18.1125 +        opt->prev1IsChar = False;
 18.1126 +      }
 18.1127 +      if (len == matches[offs])
 18.1128 +      {
 18.1129 +        offs += 2;
 18.1130 +        if (offs == numPairs)
 18.1131 +          break;
 18.1132 +      }
 18.1133 +    }
 18.1134 +  }
 18.1135 +
 18.1136 +  cur = 0;
 18.1137 +
 18.1138 +    #ifdef SHOW_STAT2
 18.1139 +    if (position >= 0)
 18.1140 +    {
 18.1141 +      unsigned i;
 18.1142 +      printf("\n pos = %4X", position);
 18.1143 +      for (i = cur; i <= lenEnd; i++)
 18.1144 +      printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
 18.1145 +    }
 18.1146 +    #endif
 18.1147 +
 18.1148 +  for (;;)
 18.1149 +  {
 18.1150 +    UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;
 18.1151 +    UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;
 18.1152 +    Bool nextIsChar;
 18.1153 +    Byte curByte, matchByte;
 18.1154 +    const Byte *data;
 18.1155 +    COptimal *curOpt;
 18.1156 +    COptimal *nextOpt;
 18.1157 +
 18.1158 +    cur++;
 18.1159 +    if (cur == lenEnd)
 18.1160 +      return Backward(p, backRes, cur);
 18.1161 +
 18.1162 +    newLen = ReadMatchDistances(p, &numPairs);
 18.1163 +    if (newLen >= p->numFastBytes)
 18.1164 +    {
 18.1165 +      p->numPairs = numPairs;
 18.1166 +      p->longestMatchLength = newLen;
 18.1167 +      return Backward(p, backRes, cur);
 18.1168 +    }
 18.1169 +    position++;
 18.1170 +    curOpt = &p->opt[cur];
 18.1171 +    posPrev = curOpt->posPrev;
 18.1172 +    if (curOpt->prev1IsChar)
 18.1173 +    {
 18.1174 +      posPrev--;
 18.1175 +      if (curOpt->prev2)
 18.1176 +      {
 18.1177 +        state = p->opt[curOpt->posPrev2].state;
 18.1178 +        if (curOpt->backPrev2 < LZMA_NUM_REPS)
 18.1179 +          state = kRepNextStates[state];
 18.1180 +        else
 18.1181 +          state = kMatchNextStates[state];
 18.1182 +      }
 18.1183 +      else
 18.1184 +        state = p->opt[posPrev].state;
 18.1185 +      state = kLiteralNextStates[state];
 18.1186 +    }
 18.1187 +    else
 18.1188 +      state = p->opt[posPrev].state;
 18.1189 +    if (posPrev == cur - 1)
 18.1190 +    {
 18.1191 +      if (IsShortRep(curOpt))
 18.1192 +        state = kShortRepNextStates[state];
 18.1193 +      else
 18.1194 +        state = kLiteralNextStates[state];
 18.1195 +    }
 18.1196 +    else
 18.1197 +    {
 18.1198 +      UInt32 pos;
 18.1199 +      const COptimal *prevOpt;
 18.1200 +      if (curOpt->prev1IsChar && curOpt->prev2)
 18.1201 +      {
 18.1202 +        posPrev = curOpt->posPrev2;
 18.1203 +        pos = curOpt->backPrev2;
 18.1204 +        state = kRepNextStates[state];
 18.1205 +      }
 18.1206 +      else
 18.1207 +      {
 18.1208 +        pos = curOpt->backPrev;
 18.1209 +        if (pos < LZMA_NUM_REPS)
 18.1210 +          state = kRepNextStates[state];
 18.1211 +        else
 18.1212 +          state = kMatchNextStates[state];
 18.1213 +      }
 18.1214 +      prevOpt = &p->opt[posPrev];
 18.1215 +      if (pos < LZMA_NUM_REPS)
 18.1216 +      {
 18.1217 +        UInt32 i;
 18.1218 +        reps[0] = prevOpt->backs[pos];
 18.1219 +        for (i = 1; i <= pos; i++)
 18.1220 +          reps[i] = prevOpt->backs[i - 1];
 18.1221 +        for (; i < LZMA_NUM_REPS; i++)
 18.1222 +          reps[i] = prevOpt->backs[i];
 18.1223 +      }
 18.1224 +      else
 18.1225 +      {
 18.1226 +        UInt32 i;
 18.1227 +        reps[0] = (pos - LZMA_NUM_REPS);
 18.1228 +        for (i = 1; i < LZMA_NUM_REPS; i++)
 18.1229 +          reps[i] = prevOpt->backs[i - 1];
 18.1230 +      }
 18.1231 +    }
 18.1232 +    curOpt->state = (CState)state;
 18.1233 +
 18.1234 +    curOpt->backs[0] = reps[0];
 18.1235 +    curOpt->backs[1] = reps[1];
 18.1236 +    curOpt->backs[2] = reps[2];
 18.1237 +    curOpt->backs[3] = reps[3];
 18.1238 +
 18.1239 +    curPrice = curOpt->price;
 18.1240 +    nextIsChar = False;
 18.1241 +    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
 18.1242 +    curByte = *data;
 18.1243 +    matchByte = *(data - (reps[0] + 1));
 18.1244 +
 18.1245 +    posState = (position & p->pbMask);
 18.1246 +
 18.1247 +    curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
 18.1248 +    {
 18.1249 +      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
 18.1250 +      curAnd1Price +=
 18.1251 +        (!IsCharState(state) ?
 18.1252 +          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
 18.1253 +          LitEnc_GetPrice(probs, curByte, p->ProbPrices));
 18.1254 +    }
 18.1255 +
 18.1256 +    nextOpt = &p->opt[cur + 1];
 18.1257 +
 18.1258 +    if (curAnd1Price < nextOpt->price)
 18.1259 +    {
 18.1260 +      nextOpt->price = curAnd1Price;
 18.1261 +      nextOpt->posPrev = cur;
 18.1262 +      MakeAsChar(nextOpt);
 18.1263 +      nextIsChar = True;
 18.1264 +    }
 18.1265 +
 18.1266 +    matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
 18.1267 +    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
 18.1268 +    
 18.1269 +    if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
 18.1270 +    {
 18.1271 +      UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
 18.1272 +      if (shortRepPrice <= nextOpt->price)
 18.1273 +      {
 18.1274 +        nextOpt->price = shortRepPrice;
 18.1275 +        nextOpt->posPrev = cur;
 18.1276 +        MakeAsShortRep(nextOpt);
 18.1277 +        nextIsChar = True;
 18.1278 +      }
 18.1279 +    }
 18.1280 +    numAvailFull = p->numAvail;
 18.1281 +    {
 18.1282 +      UInt32 temp = kNumOpts - 1 - cur;
 18.1283 +      if (temp < numAvailFull)
 18.1284 +        numAvailFull = temp;
 18.1285 +    }
 18.1286 +
 18.1287 +    if (numAvailFull < 2)
 18.1288 +      continue;
 18.1289 +    numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
 18.1290 +
 18.1291 +    if (!nextIsChar && matchByte != curByte) /* speed optimization */
 18.1292 +    {
 18.1293 +      /* try Literal + rep0 */
 18.1294 +      UInt32 temp;
 18.1295 +      UInt32 lenTest2;
 18.1296 +      const Byte *data2 = data - (reps[0] + 1);
 18.1297 +      UInt32 limit = p->numFastBytes + 1;
 18.1298 +      if (limit > numAvailFull)
 18.1299 +        limit = numAvailFull;
 18.1300 +
 18.1301 +      for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
 18.1302 +      lenTest2 = temp - 1;
 18.1303 +      if (lenTest2 >= 2)
 18.1304 +      {
 18.1305 +        UInt32 state2 = kLiteralNextStates[state];
 18.1306 +        UInt32 posStateNext = (position + 1) & p->pbMask;
 18.1307 +        UInt32 nextRepMatchPrice = curAnd1Price +
 18.1308 +            GET_PRICE_1(p->isMatch[state2][posStateNext]) +
 18.1309 +            GET_PRICE_1(p->isRep[state2]);
 18.1310 +        /* for (; lenTest2 >= 2; lenTest2--) */
 18.1311 +        {
 18.1312 +          UInt32 curAndLenPrice;
 18.1313 +          COptimal *opt;
 18.1314 +          UInt32 offset = cur + 1 + lenTest2;
 18.1315 +          while (lenEnd < offset)
 18.1316 +            p->opt[++lenEnd].price = kInfinityPrice;
 18.1317 +          curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
 18.1318 +          opt = &p->opt[offset];
 18.1319 +          if (curAndLenPrice < opt->price)
 18.1320 +          {
 18.1321 +            opt->price = curAndLenPrice;
 18.1322 +            opt->posPrev = cur + 1;
 18.1323 +            opt->backPrev = 0;
 18.1324 +            opt->prev1IsChar = True;
 18.1325 +            opt->prev2 = False;
 18.1326 +          }
 18.1327 +        }
 18.1328 +      }
 18.1329 +    }
 18.1330 +    
 18.1331 +    startLen = 2; /* speed optimization */
 18.1332 +    {
 18.1333 +    UInt32 repIndex;
 18.1334 +    for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
 18.1335 +    {
 18.1336 +      UInt32 lenTest;
 18.1337 +      UInt32 lenTestTemp;
 18.1338 +      UInt32 price;
 18.1339 +      const Byte *data2 = data - (reps[repIndex] + 1);
 18.1340 +      if (data[0] != data2[0] || data[1] != data2[1])
 18.1341 +        continue;
 18.1342 +      for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
 18.1343 +      while (lenEnd < cur + lenTest)
 18.1344 +        p->opt[++lenEnd].price = kInfinityPrice;
 18.1345 +      lenTestTemp = lenTest;
 18.1346 +      price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
 18.1347 +      do
 18.1348 +      {
 18.1349 +        UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
 18.1350 +        COptimal *opt = &p->opt[cur + lenTest];
 18.1351 +        if (curAndLenPrice < opt->price)
 18.1352 +        {
 18.1353 +          opt->price = curAndLenPrice;
 18.1354 +          opt->posPrev = cur;
 18.1355 +          opt->backPrev = repIndex;
 18.1356 +          opt->prev1IsChar = False;
 18.1357 +        }
 18.1358 +      }
 18.1359 +      while (--lenTest >= 2);
 18.1360 +      lenTest = lenTestTemp;
 18.1361 +      
 18.1362 +      if (repIndex == 0)
 18.1363 +        startLen = lenTest + 1;
 18.1364 +        
 18.1365 +      /* if (_maxMode) */
 18.1366 +        {
 18.1367 +          UInt32 lenTest2 = lenTest + 1;
 18.1368 +          UInt32 limit = lenTest2 + p->numFastBytes;
 18.1369 +          UInt32 nextRepMatchPrice;
 18.1370 +          if (limit > numAvailFull)
 18.1371 +            limit = numAvailFull;
 18.1372 +          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
 18.1373 +          lenTest2 -= lenTest + 1;
 18.1374 +          if (lenTest2 >= 2)
 18.1375 +          {
 18.1376 +            UInt32 state2 = kRepNextStates[state];
 18.1377 +            UInt32 posStateNext = (position + lenTest) & p->pbMask;
 18.1378 +            UInt32 curAndLenCharPrice =
 18.1379 +                price + p->repLenEnc.prices[posState][lenTest - 2] +
 18.1380 +                GET_PRICE_0(p->isMatch[state2][posStateNext]) +
 18.1381 +                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
 18.1382 +                    data[lenTest], data2[lenTest], p->ProbPrices);
 18.1383 +            state2 = kLiteralNextStates[state2];
 18.1384 +            posStateNext = (position + lenTest + 1) & p->pbMask;
 18.1385 +            nextRepMatchPrice = curAndLenCharPrice +
 18.1386 +                GET_PRICE_1(p->isMatch[state2][posStateNext]) +
 18.1387 +                GET_PRICE_1(p->isRep[state2]);
 18.1388 +            
 18.1389 +            /* for (; lenTest2 >= 2; lenTest2--) */
 18.1390 +            {
 18.1391 +              UInt32 curAndLenPrice;
 18.1392 +              COptimal *opt;
 18.1393 +              UInt32 offset = cur + lenTest + 1 + lenTest2;
 18.1394 +              while (lenEnd < offset)
 18.1395 +                p->opt[++lenEnd].price = kInfinityPrice;
 18.1396 +              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
 18.1397 +              opt = &p->opt[offset];
 18.1398 +              if (curAndLenPrice < opt->price)
 18.1399 +              {
 18.1400 +                opt->price = curAndLenPrice;
 18.1401 +                opt->posPrev = cur + lenTest + 1;
 18.1402 +                opt->backPrev = 0;
 18.1403 +                opt->prev1IsChar = True;
 18.1404 +                opt->prev2 = True;
 18.1405 +                opt->posPrev2 = cur;
 18.1406 +                opt->backPrev2 = repIndex;
 18.1407 +              }
 18.1408 +            }
 18.1409 +          }
 18.1410 +        }
 18.1411 +    }
 18.1412 +    }
 18.1413 +    /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
 18.1414 +    if (newLen > numAvail)
 18.1415 +    {
 18.1416 +      newLen = numAvail;
 18.1417 +      for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);
 18.1418 +      matches[numPairs] = newLen;
 18.1419 +      numPairs += 2;
 18.1420 +    }
 18.1421 +    if (newLen >= startLen)
 18.1422 +    {
 18.1423 +      UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
 18.1424 +      UInt32 offs, curBack, posSlot;
 18.1425 +      UInt32 lenTest;
 18.1426 +      while (lenEnd < cur + newLen)
 18.1427 +        p->opt[++lenEnd].price = kInfinityPrice;
 18.1428 +
 18.1429 +      offs = 0;
 18.1430 +      while (startLen > matches[offs])
 18.1431 +        offs += 2;
 18.1432 +      curBack = matches[offs + 1];
 18.1433 +      GetPosSlot2(curBack, posSlot);
 18.1434 +      for (lenTest = /*2*/ startLen; ; lenTest++)
 18.1435 +      {
 18.1436 +        UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
 18.1437 +        UInt32 lenToPosState = GetLenToPosState(lenTest);
 18.1438 +        COptimal *opt;
 18.1439 +        if (curBack < kNumFullDistances)
 18.1440 +          curAndLenPrice += p->distancesPrices[lenToPosState][curBack];
 18.1441 +        else
 18.1442 +          curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];
 18.1443 +        
 18.1444 +        opt = &p->opt[cur + lenTest];
 18.1445 +        if (curAndLenPrice < opt->price)
 18.1446 +        {
 18.1447 +          opt->price = curAndLenPrice;
 18.1448 +          opt->posPrev = cur;
 18.1449 +          opt->backPrev = curBack + LZMA_NUM_REPS;
 18.1450 +          opt->prev1IsChar = False;
 18.1451 +        }
 18.1452 +
 18.1453 +        if (/*_maxMode && */lenTest == matches[offs])
 18.1454 +        {
 18.1455 +          /* Try Match + Literal + Rep0 */
 18.1456 +          const Byte *data2 = data - (curBack + 1);
 18.1457 +          UInt32 lenTest2 = lenTest + 1;
 18.1458 +          UInt32 limit = lenTest2 + p->numFastBytes;
 18.1459 +          UInt32 nextRepMatchPrice;
 18.1460 +          if (limit > numAvailFull)
 18.1461 +            limit = numAvailFull;
 18.1462 +          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
 18.1463 +          lenTest2 -= lenTest + 1;
 18.1464 +          if (lenTest2 >= 2)
 18.1465 +          {
 18.1466 +            UInt32 state2 = kMatchNextStates[state];
 18.1467 +            UInt32 posStateNext = (position + lenTest) & p->pbMask;
 18.1468 +            UInt32 curAndLenCharPrice = curAndLenPrice +
 18.1469 +                GET_PRICE_0(p->isMatch[state2][posStateNext]) +
 18.1470 +                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
 18.1471 +                    data[lenTest], data2[lenTest], p->ProbPrices);
 18.1472 +            state2 = kLiteralNextStates[state2];
 18.1473 +            posStateNext = (posStateNext + 1) & p->pbMask;
 18.1474 +            nextRepMatchPrice = curAndLenCharPrice +
 18.1475 +                GET_PRICE_1(p->isMatch[state2][posStateNext]) +
 18.1476 +                GET_PRICE_1(p->isRep[state2]);
 18.1477 +            
 18.1478 +            /* for (; lenTest2 >= 2; lenTest2--) */
 18.1479 +            {
 18.1480 +              UInt32 offset = cur + lenTest + 1 + lenTest2;
 18.1481 +              UInt32 curAndLenPrice;
 18.1482 +              COptimal *opt;
 18.1483 +              while (lenEnd < offset)
 18.1484 +                p->opt[++lenEnd].price = kInfinityPrice;
 18.1485 +              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
 18.1486 +              opt = &p->opt[offset];
 18.1487 +              if (curAndLenPrice < opt->price)
 18.1488 +              {
 18.1489 +                opt->price = curAndLenPrice;
 18.1490 +                opt->posPrev = cur + lenTest + 1;
 18.1491 +                opt->backPrev = 0;
 18.1492 +                opt->prev1IsChar = True;
 18.1493 +                opt->prev2 = True;
 18.1494 +                opt->posPrev2 = cur;
 18.1495 +                opt->backPrev2 = curBack + LZMA_NUM_REPS;
 18.1496 +              }
 18.1497 +            }
 18.1498 +          }
 18.1499 +          offs += 2;
 18.1500 +          if (offs == numPairs)
 18.1501 +            break;
 18.1502 +          curBack = matches[offs + 1];
 18.1503 +          if (curBack >= kNumFullDistances)
 18.1504 +            GetPosSlot2(curBack, posSlot);
 18.1505 +        }
 18.1506 +      }
 18.1507 +    }
 18.1508 +  }
 18.1509 +}
 18.1510 +
 18.1511 +#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
 18.1512 +
 18.1513 +static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
 18.1514 +{
 18.1515 +  UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;
 18.1516 +  const Byte *data;
 18.1517 +  const UInt32 *matches;
 18.1518 +
 18.1519 +  if (p->additionalOffset == 0)
 18.1520 +    mainLen = ReadMatchDistances(p, &numPairs);
 18.1521 +  else
 18.1522 +  {
 18.1523 +    mainLen = p->longestMatchLength;
 18.1524 +    numPairs = p->numPairs;
 18.1525 +  }
 18.1526 +
 18.1527 +  numAvail = p->numAvail;
 18.1528 +  *backRes = (UInt32)-1;
 18.1529 +  if (numAvail < 2)
 18.1530 +    return 1;
 18.1531 +  if (numAvail > LZMA_MATCH_LEN_MAX)
 18.1532 +    numAvail = LZMA_MATCH_LEN_MAX;
 18.1533 +  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
 18.1534 +
 18.1535 +  repLen = repIndex = 0;
 18.1536 +  for (i = 0; i < LZMA_NUM_REPS; i++)
 18.1537 +  {
 18.1538 +    UInt32 len;
 18.1539 +    const Byte *data2 = data - (p->reps[i] + 1);
 18.1540 +    if (data[0] != data2[0] || data[1] != data2[1])
 18.1541 +      continue;
 18.1542 +    for (len = 2; len < numAvail && data[len] == data2[len]; len++);
 18.1543 +    if (len >= p->numFastBytes)
 18.1544 +    {
 18.1545 +      *backRes = i;
 18.1546 +      MovePos(p, len - 1);
 18.1547 +      return len;
 18.1548 +    }
 18.1549 +    if (len > repLen)
 18.1550 +    {
 18.1551 +      repIndex = i;
 18.1552 +      repLen = len;
 18.1553 +    }
 18.1554 +  }
 18.1555 +
 18.1556 +  matches = p->matches;
 18.1557 +  if (mainLen >= p->numFastBytes)
 18.1558 +  {
 18.1559 +    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
 18.1560 +    MovePos(p, mainLen - 1);
 18.1561 +    return mainLen;
 18.1562 +  }
 18.1563 +
 18.1564 +  mainDist = 0; /* for GCC */
 18.1565 +  if (mainLen >= 2)
 18.1566 +  {
 18.1567 +    mainDist = matches[numPairs - 1];
 18.1568 +    while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)
 18.1569 +    {
 18.1570 +      if (!ChangePair(matches[numPairs - 3], mainDist))
 18.1571 +        break;
 18.1572 +      numPairs -= 2;
 18.1573 +      mainLen = matches[numPairs - 2];
 18.1574 +      mainDist = matches[numPairs - 1];
 18.1575 +    }
 18.1576 +    if (mainLen == 2 && mainDist >= 0x80)
 18.1577 +      mainLen = 1;
 18.1578 +  }
 18.1579 +
 18.1580 +  if (repLen >= 2 && (
 18.1581 +        (repLen + 1 >= mainLen) ||
 18.1582 +        (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||
 18.1583 +        (repLen + 3 >= mainLen && mainDist >= (1 << 15))))
 18.1584 +  {
 18.1585 +    *backRes = repIndex;
 18.1586 +    MovePos(p, repLen - 1);
 18.1587 +    return repLen;
 18.1588 +  }
 18.1589 +  
 18.1590 +  if (mainLen < 2 || numAvail <= 2)
 18.1591 +    return 1;
 18.1592 +
 18.1593 +  p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);
 18.1594 +  if (p->longestMatchLength >= 2)
 18.1595 +  {
 18.1596 +    UInt32 newDistance = matches[p->numPairs - 1];
 18.1597 +    if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||
 18.1598 +        (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||
 18.1599 +        (p->longestMatchLength > mainLen + 1) ||
 18.1600 +        (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))
 18.1601 +      return 1;
 18.1602 +  }
 18.1603 +  
 18.1604 +  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
 18.1605 +  for (i = 0; i < LZMA_NUM_REPS; i++)
 18.1606 +  {
 18.1607 +    UInt32 len, limit;
 18.1608 +    const Byte *data2 = data - (p->reps[i] + 1);
 18.1609 +    if (data[0] != data2[0] || data[1] != data2[1])
 18.1610 +      continue;
 18.1611 +    limit = mainLen - 1;
 18.1612 +    for (len = 2; len < limit && data[len] == data2[len]; len++);
 18.1613 +    if (len >= limit)
 18.1614 +      return 1;
 18.1615 +  }
 18.1616 +  *backRes = mainDist + LZMA_NUM_REPS;
 18.1617 +  MovePos(p, mainLen - 2);
 18.1618 +  return mainLen;
 18.1619 +}
 18.1620 +
 18.1621 +static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
 18.1622 +{
 18.1623 +  UInt32 len;
 18.1624 +  RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
 18.1625 +  RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
 18.1626 +  p->state = kMatchNextStates[p->state];
 18.1627 +  len = LZMA_MATCH_LEN_MIN;
 18.1628 +  LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
 18.1629 +  RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);
 18.1630 +  RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);
 18.1631 +  RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
 18.1632 +}
 18.1633 +
 18.1634 +static SRes CheckErrors(CLzmaEnc *p)
 18.1635 +{
 18.1636 +  if (p->result != SZ_OK)
 18.1637 +    return p->result;
 18.1638 +  if (p->rc.res != SZ_OK)
 18.1639 +    p->result = SZ_ERROR_WRITE;
 18.1640 +  if (p->matchFinderBase.result != SZ_OK)
 18.1641 +    p->result = SZ_ERROR_READ;
 18.1642 +  if (p->result != SZ_OK)
 18.1643 +    p->finished = True;
 18.1644 +  return p->result;
 18.1645 +}
 18.1646 +
 18.1647 +static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
 18.1648 +{
 18.1649 +  /* ReleaseMFStream(); */
 18.1650 +  p->finished = True;
 18.1651 +  if (p->writeEndMark)
 18.1652 +    WriteEndMarker(p, nowPos & p->pbMask);
 18.1653 +  RangeEnc_FlushData(&p->rc);
 18.1654 +  RangeEnc_FlushStream(&p->rc);
 18.1655 +  return CheckErrors(p);
 18.1656 +}
 18.1657 +
 18.1658 +static void FillAlignPrices(CLzmaEnc *p)
 18.1659 +{
 18.1660 +  UInt32 i;
 18.1661 +  for (i = 0; i < kAlignTableSize; i++)
 18.1662 +    p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
 18.1663 +  p->alignPriceCount = 0;
 18.1664 +}
 18.1665 +
 18.1666 +static void FillDistancesPrices(CLzmaEnc *p)
 18.1667 +{
 18.1668 +  UInt32 tempPrices[kNumFullDistances];
 18.1669 +  UInt32 i, lenToPosState;
 18.1670 +  for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
 18.1671 +  {
 18.1672 +    UInt32 posSlot = GetPosSlot1(i);
 18.1673 +    UInt32 footerBits = ((posSlot >> 1) - 1);
 18.1674 +    UInt32 base = ((2 | (posSlot & 1)) << footerBits);
 18.1675 +    tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);
 18.1676 +  }
 18.1677 +
 18.1678 +  for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
 18.1679 +  {
 18.1680 +    UInt32 posSlot;
 18.1681 +    const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
 18.1682 +    UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
 18.1683 +    for (posSlot = 0; posSlot < p->distTableSize; posSlot++)
 18.1684 +      posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
 18.1685 +    for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)
 18.1686 +      posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
 18.1687 +
 18.1688 +    {
 18.1689 +      UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
 18.1690 +      UInt32 i;
 18.1691 +      for (i = 0; i < kStartPosModelIndex; i++)
 18.1692 +        distancesPrices[i] = posSlotPrices[i];
 18.1693 +      for (; i < kNumFullDistances; i++)
 18.1694 +        distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
 18.1695 +    }
 18.1696 +  }
 18.1697 +  p->matchPriceCount = 0;
 18.1698 +}
 18.1699 +
 18.1700 +void LzmaEnc_Construct(CLzmaEnc *p)
 18.1701 +{
 18.1702 +  RangeEnc_Construct(&p->rc);
 18.1703 +  MatchFinder_Construct(&p->matchFinderBase);
 18.1704 +  #ifdef COMPRESS_MF_MT
 18.1705 +  MatchFinderMt_Construct(&p->matchFinderMt);
 18.1706 +  p->matchFinderMt.MatchFinder = &p->matchFinderBase;
 18.1707 +  #endif
 18.1708 +
 18.1709 +  {
 18.1710 +    CLzmaEncProps props;
 18.1711 +    LzmaEncProps_Init(&props);
 18.1712 +    LzmaEnc_SetProps(p, &props);
 18.1713 +  }
 18.1714 +
 18.1715 +  #ifndef LZMA_LOG_BSR
 18.1716 +  LzmaEnc_FastPosInit(p->g_FastPos);
 18.1717 +  #endif
 18.1718 +
 18.1719 +  LzmaEnc_InitPriceTables(p->ProbPrices);
 18.1720 +  p->litProbs = 0;
 18.1721 +  p->saveState.litProbs = 0;
 18.1722 +}
 18.1723 +
 18.1724 +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
 18.1725 +{
 18.1726 +  void *p;
 18.1727 +  p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
 18.1728 +  if (p != 0)
 18.1729 +    LzmaEnc_Construct((CLzmaEnc *)p);
 18.1730 +  return p;
 18.1731 +}
 18.1732 +
 18.1733 +void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
 18.1734 +{
 18.1735 +  alloc->Free(alloc, p->litProbs);
 18.1736 +  alloc->Free(alloc, p->saveState.litProbs);
 18.1737 +  p->litProbs = 0;
 18.1738 +  p->saveState.litProbs = 0;
 18.1739 +}
 18.1740 +
 18.1741 +void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
 18.1742 +{
 18.1743 +  #ifdef COMPRESS_MF_MT
 18.1744 +  MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
 18.1745 +  #endif
 18.1746 +  MatchFinder_Free(&p->matchFinderBase, allocBig);
 18.1747 +  LzmaEnc_FreeLits(p, alloc);
 18.1748 +  RangeEnc_Free(&p->rc, alloc);
 18.1749 +}
 18.1750 +
 18.1751 +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
 18.1752 +{
 18.1753 +  LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
 18.1754 +  alloc->Free(alloc, p);
 18.1755 +}
 18.1756 +
 18.1757 +static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
 18.1758 +{
 18.1759 +  UInt32 nowPos32, startPos32;
 18.1760 +  if (p->inStream != 0)
 18.1761 +  {
 18.1762 +    p->matchFinderBase.stream = p->inStream;
 18.1763 +    p->matchFinder.Init(p->matchFinderObj);
 18.1764 +    p->inStream = 0;
 18.1765 +  }
 18.1766 +
 18.1767 +  if (p->finished)
 18.1768 +    return p->result;
 18.1769 +  RINOK(CheckErrors(p));
 18.1770 +
 18.1771 +  nowPos32 = (UInt32)p->nowPos64;
 18.1772 +  startPos32 = nowPos32;
 18.1773 +
 18.1774 +  if (p->nowPos64 == 0)
 18.1775 +  {
 18.1776 +    UInt32 numPairs;
 18.1777 +    Byte curByte;
 18.1778 +    if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
 18.1779 +      return Flush(p, nowPos32);
 18.1780 +    ReadMatchDistances(p, &numPairs);
 18.1781 +    RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
 18.1782 +    p->state = kLiteralNextStates[p->state];
 18.1783 +    curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
 18.1784 +    LitEnc_Encode(&p->rc, p->litProbs, curByte);
 18.1785 +    p->additionalOffset--;
 18.1786 +    nowPos32++;
 18.1787 +  }
 18.1788 +
 18.1789 +  if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
 18.1790 +  for (;;)
 18.1791 +  {
 18.1792 +    UInt32 pos, len, posState;
 18.1793 +
 18.1794 +    if (p->fastMode)
 18.1795 +      len = GetOptimumFast(p, &pos);
 18.1796 +    else
 18.1797 +      len = GetOptimum(p, nowPos32, &pos);
 18.1798 +
 18.1799 +    #ifdef SHOW_STAT2
 18.1800 +    printf("\n pos = %4X,   len = %d   pos = %d", nowPos32, len, pos);
 18.1801 +    #endif
 18.1802 +
 18.1803 +    posState = nowPos32 & p->pbMask;
 18.1804 +    if (len == 1 && pos == (UInt32)-1)
 18.1805 +    {
 18.1806 +      Byte curByte;
 18.1807 +      CLzmaProb *probs;
 18.1808 +      const Byte *data;
 18.1809 +
 18.1810 +      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);
 18.1811 +      data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
 18.1812 +      curByte = *data;
 18.1813 +      probs = LIT_PROBS(nowPos32, *(data - 1));
 18.1814 +      if (IsCharState(p->state))
 18.1815 +        LitEnc_Encode(&p->rc, probs, curByte);
 18.1816 +      else
 18.1817 +        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));
 18.1818 +      p->state = kLiteralNextStates[p->state];
 18.1819 +    }
 18.1820 +    else
 18.1821 +    {
 18.1822 +      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
 18.1823 +      if (pos < LZMA_NUM_REPS)
 18.1824 +      {
 18.1825 +        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);
 18.1826 +        if (pos == 0)
 18.1827 +        {
 18.1828 +          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);
 18.1829 +          RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));
 18.1830 +        }
 18.1831 +        else
 18.1832 +        {
 18.1833 +          UInt32 distance = p->reps[pos];
 18.1834 +          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);
 18.1835 +          if (pos == 1)
 18.1836 +            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);
 18.1837 +          else
 18.1838 +          {
 18.1839 +            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);
 18.1840 +            RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);
 18.1841 +            if (pos == 3)
 18.1842 +              p->reps[3] = p->reps[2];
 18.1843 +            p->reps[2] = p->reps[1];
 18.1844 +          }
 18.1845 +          p->reps[1] = p->reps[0];
 18.1846 +          p->reps[0] = distance;
 18.1847 +        }
 18.1848 +        if (len == 1)
 18.1849 +          p->state = kShortRepNextStates[p->state];
 18.1850 +        else
 18.1851 +        {
 18.1852 +          LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
 18.1853 +          p->state = kRepNextStates[p->state];
 18.1854 +        }
 18.1855 +      }
 18.1856 +      else
 18.1857 +      {
 18.1858 +        UInt32 posSlot;
 18.1859 +        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
 18.1860 +        p->state = kMatchNextStates[p->state];
 18.1861 +        LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
 18.1862 +        pos -= LZMA_NUM_REPS;
 18.1863 +        GetPosSlot(pos, posSlot);
 18.1864 +        RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
 18.1865 +        
 18.1866 +        if (posSlot >= kStartPosModelIndex)
 18.1867 +        {
 18.1868 +          UInt32 footerBits = ((posSlot >> 1) - 1);
 18.1869 +          UInt32 base = ((2 | (posSlot & 1)) << footerBits);
 18.1870 +          UInt32 posReduced = pos - base;
 18.1871 +
 18.1872 +          if (posSlot < kEndPosModelIndex)
 18.1873 +            RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);
 18.1874 +          else
 18.1875 +          {
 18.1876 +            RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
 18.1877 +            RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
 18.1878 +            p->alignPriceCount++;
 18.1879 +          }
 18.1880 +        }
 18.1881 +        p->reps[3] = p->reps[2];
 18.1882 +        p->reps[2] = p->reps[1];
 18.1883 +        p->reps[1] = p->reps[0];
 18.1884 +        p->reps[0] = pos;
 18.1885 +        p->matchPriceCount++;
 18.1886 +      }
 18.1887 +    }
 18.1888 +    p->additionalOffset -= len;
 18.1889 +    nowPos32 += len;
 18.1890 +    if (p->additionalOffset == 0)
 18.1891 +    {
 18.1892 +      UInt32 processed;
 18.1893 +      if (!p->fastMode)
 18.1894 +      {
 18.1895 +        if (p->matchPriceCount >= (1 << 7))
 18.1896 +          FillDistancesPrices(p);
 18.1897 +        if (p->alignPriceCount >= kAlignTableSize)
 18.1898 +          FillAlignPrices(p);
 18.1899 +      }
 18.1900 +      if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
 18.1901 +        break;
 18.1902 +      processed = nowPos32 - startPos32;
 18.1903 +      if (useLimits)
 18.1904 +      {
 18.1905 +        if (processed + kNumOpts + 300 >= maxUnpackSize ||
 18.1906 +            RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
 18.1907 +          break;
 18.1908 +      }
 18.1909 +      else if (processed >= (1 << 15))
 18.1910 +      {
 18.1911 +        p->nowPos64 += nowPos32 - startPos32;
 18.1912 +        return CheckErrors(p);
 18.1913 +      }
 18.1914 +    }
 18.1915 +  }
 18.1916 +  p->nowPos64 += nowPos32 - startPos32;
 18.1917 +  return Flush(p, nowPos32);
 18.1918 +}
 18.1919 +
 18.1920 +#define kBigHashDicLimit ((UInt32)1 << 24)
 18.1921 +
 18.1922 +static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
 18.1923 +{
 18.1924 +  UInt32 beforeSize = kNumOpts;
 18.1925 +  Bool btMode;
 18.1926 +  if (!RangeEnc_Alloc(&p->rc, alloc))
 18.1927 +    return SZ_ERROR_MEM;
 18.1928 +  btMode = (p->matchFinderBase.btMode != 0);
 18.1929 +  #ifdef COMPRESS_MF_MT
 18.1930 +  p->mtMode = (p->multiThread && !p->fastMode && btMode);
 18.1931 +  #endif
 18.1932 +
 18.1933 +  {
 18.1934 +    unsigned lclp = p->lc + p->lp;
 18.1935 +    if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
 18.1936 +    {
 18.1937 +      LzmaEnc_FreeLits(p, alloc);
 18.1938 +      p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
 18.1939 +      p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
 18.1940 +      if (p->litProbs == 0 || p->saveState.litProbs == 0)
 18.1941 +      {
 18.1942 +        LzmaEnc_FreeLits(p, alloc);
 18.1943 +        return SZ_ERROR_MEM;
 18.1944 +      }
 18.1945 +      p->lclp = lclp;
 18.1946 +    }
 18.1947 +  }
 18.1948 +
 18.1949 +  p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
 18.1950 +
 18.1951 +  if (beforeSize + p->dictSize < keepWindowSize)
 18.1952 +    beforeSize = keepWindowSize - p->dictSize;
 18.1953 +
 18.1954 +  #ifdef COMPRESS_MF_MT
 18.1955 +  if (p->mtMode)
 18.1956 +  {
 18.1957 +    RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
 18.1958 +    p->matchFinderObj = &p->matchFinderMt;
 18.1959 +    MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
 18.1960 +  }
 18.1961 +  else
 18.1962 +  #endif
 18.1963 +  {
 18.1964 +    if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
 18.1965 +      return SZ_ERROR_MEM;
 18.1966 +    p->matchFinderObj = &p->matchFinderBase;
 18.1967 +    MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
 18.1968 +  }
 18.1969 +  return SZ_OK;
 18.1970 +}
 18.1971 +
 18.1972 +void LzmaEnc_Init(CLzmaEnc *p)
 18.1973 +{
 18.1974 +  UInt32 i;
 18.1975 +  p->state = 0;
 18.1976 +  for (i = 0 ; i < LZMA_NUM_REPS; i++)
 18.1977 +    p->reps[i] = 0;
 18.1978 +
 18.1979 +  RangeEnc_Init(&p->rc);
 18.1980 +
 18.1981 +
 18.1982 +  for (i = 0; i < kNumStates; i++)
 18.1983 +  {
 18.1984 +    UInt32 j;
 18.1985 +    for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
 18.1986 +    {
 18.1987 +      p->isMatch[i][j] = kProbInitValue;
 18.1988 +      p->isRep0Long[i][j] = kProbInitValue;
 18.1989 +    }
 18.1990 +    p->isRep[i] = kProbInitValue;
 18.1991 +    p->isRepG0[i] = kProbInitValue;
 18.1992 +    p->isRepG1[i] = kProbInitValue;
 18.1993 +    p->isRepG2[i] = kProbInitValue;
 18.1994 +  }
 18.1995 +
 18.1996 +  {
 18.1997 +    UInt32 num = 0x300 << (p->lp + p->lc);
 18.1998 +    for (i = 0; i < num; i++)
 18.1999 +      p->litProbs[i] = kProbInitValue;
 18.2000 +  }
 18.2001 +
 18.2002 +  {
 18.2003 +    for (i = 0; i < kNumLenToPosStates; i++)
 18.2004 +    {
 18.2005 +      CLzmaProb *probs = p->posSlotEncoder[i];
 18.2006 +      UInt32 j;
 18.2007 +      for (j = 0; j < (1 << kNumPosSlotBits); j++)
 18.2008 +        probs[j] = kProbInitValue;
 18.2009 +    }
 18.2010 +  }
 18.2011 +  {
 18.2012 +    for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
 18.2013 +      p->posEncoders[i] = kProbInitValue;
 18.2014 +  }
 18.2015 +
 18.2016 +  LenEnc_Init(&p->lenEnc.p);
 18.2017 +  LenEnc_Init(&p->repLenEnc.p);
 18.2018 +
 18.2019 +  for (i = 0; i < (1 << kNumAlignBits); i++)
 18.2020 +    p->posAlignEncoder[i] = kProbInitValue;
 18.2021 +
 18.2022 +  p->optimumEndIndex = 0;
 18.2023 +  p->optimumCurrentIndex = 0;
 18.2024 +  p->additionalOffset = 0;
 18.2025 +
 18.2026 +  p->pbMask = (1 << p->pb) - 1;
 18.2027 +  p->lpMask = (1 << p->lp) - 1;
 18.2028 +}
 18.2029 +
 18.2030 +void LzmaEnc_InitPrices(CLzmaEnc *p)
 18.2031 +{
 18.2032 +  if (!p->fastMode)
 18.2033 +  {
 18.2034 +    FillDistancesPrices(p);
 18.2035 +    FillAlignPrices(p);
 18.2036 +  }
 18.2037 +
 18.2038 +  p->lenEnc.tableSize =
 18.2039 +  p->repLenEnc.tableSize =
 18.2040 +      p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
 18.2041 +  LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);
 18.2042 +  LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);
 18.2043 +}
 18.2044 +
 18.2045 +static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
 18.2046 +{
 18.2047 +  UInt32 i;
 18.2048 +  for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)
 18.2049 +    if (p->dictSize <= ((UInt32)1 << i))
 18.2050 +      break;
 18.2051 +  p->distTableSize = i * 2;
 18.2052 +
 18.2053 +  p->finished = False;
 18.2054 +  p->result = SZ_OK;
 18.2055 +  RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
 18.2056 +  LzmaEnc_Init(p);
 18.2057 +  LzmaEnc_InitPrices(p);
 18.2058 +  p->nowPos64 = 0;
 18.2059 +  return SZ_OK;
 18.2060 +}
 18.2061 +
 18.2062 +static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream,
 18.2063 +    ISzAlloc *alloc, ISzAlloc *allocBig)
 18.2064 +{
 18.2065 +  CLzmaEnc *p = (CLzmaEnc *)pp;
 18.2066 +  p->inStream = inStream;
 18.2067 +  p->rc.outStream = outStream;
 18.2068 +  return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
 18.2069 +}
 18.2070 +
 18.2071 +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
 18.2072 +    ISeqInStream *inStream, UInt32 keepWindowSize,
 18.2073 +    ISzAlloc *alloc, ISzAlloc *allocBig)
 18.2074 +{
 18.2075 +  CLzmaEnc *p = (CLzmaEnc *)pp;
 18.2076 +  p->inStream = inStream;
 18.2077 +  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
 18.2078 +}
 18.2079 +
 18.2080 +static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
 18.2081 +{
 18.2082 +  p->seqBufInStream.funcTable.Read = MyRead;
 18.2083 +  p->seqBufInStream.data = src;
 18.2084 +  p->seqBufInStream.rem = srcLen;
 18.2085 +}
 18.2086 +
 18.2087 +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
 18.2088 +    UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
 18.2089 +{
 18.2090 +  CLzmaEnc *p = (CLzmaEnc *)pp;
 18.2091 +  LzmaEnc_SetInputBuf(p, src, srcLen);
 18.2092 +  p->inStream = &p->seqBufInStream.funcTable;
 18.2093 +  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
 18.2094 +}
 18.2095 +
 18.2096 +void LzmaEnc_Finish(CLzmaEncHandle pp)
 18.2097 +{
 18.2098 +  #ifdef COMPRESS_MF_MT
 18.2099 +  CLzmaEnc *p = (CLzmaEnc *)pp;
 18.2100 +  if (p->mtMode)
 18.2101 +    MatchFinderMt_ReleaseStream(&p->matchFinderMt);
 18.2102 +  #else
 18.2103 +  pp = pp;
 18.2104 +  #endif
 18.2105 +}
 18.2106 +
 18.2107 +typedef struct _CSeqOutStreamBuf
 18.2108 +{
 18.2109 +  ISeqOutStream funcTable;
 18.2110 +  Byte *data;
 18.2111 +  SizeT rem;
 18.2112 +  Bool overflow;
 18.2113 +} CSeqOutStreamBuf;
 18.2114 +
 18.2115 +static size_t MyWrite(void *pp, const void *data, size_t size)
 18.2116 +{
 18.2117 +  CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
 18.2118 +  if (p->rem < size)
 18.2119 +  {
 18.2120 +    size = p->rem;
 18.2121 +    p->overflow = True;
 18.2122 +  }
 18.2123 +  memcpy(p->data, data, size);
 18.2124 +  p->rem -= size;
 18.2125 +  p->data += size;
 18.2126 +  return size;
 18.2127 +}
 18.2128 +
 18.2129 +
 18.2130 +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
 18.2131 +{
 18.2132 +  const CLzmaEnc *p = (CLzmaEnc *)pp;
 18.2133 +  return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
 18.2134 +}
 18.2135 +
 18.2136 +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
 18.2137 +{
 18.2138 +  const CLzmaEnc *p = (CLzmaEnc *)pp;
 18.2139 +  return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
 18.2140 +}
 18.2141 +
 18.2142 +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
 18.2143 +    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
 18.2144 +{
 18.2145 +  CLzmaEnc *p = (CLzmaEnc *)pp;
 18.2146 +  UInt64 nowPos64;
 18.2147 +  SRes res;
 18.2148 +  CSeqOutStreamBuf outStream;
 18.2149 +
 18.2150 +  outStream.funcTable.Write = MyWrite;
 18.2151 +  outStream.data = dest;
 18.2152 +  outStream.rem = *destLen;
 18.2153 +  outStream.overflow = False;
 18.2154 +
 18.2155 +  p->writeEndMark = False;
 18.2156 +  p->finished = False;
 18.2157 +  p->result = SZ_OK;
 18.2158 +
 18.2159 +  if (reInit)
 18.2160 +    LzmaEnc_Init(p);
 18.2161 +  LzmaEnc_InitPrices(p);
 18.2162 +  nowPos64 = p->nowPos64;
 18.2163 +  RangeEnc_Init(&p->rc);
 18.2164 +  p->rc.outStream = &outStream.funcTable;
 18.2165 +
 18.2166 +  res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);
 18.2167 +  
 18.2168 +  *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
 18.2169 +  *destLen -= outStream.rem;
 18.2170 +  if (outStream.overflow)
 18.2171 +    return SZ_ERROR_OUTPUT_EOF;
 18.2172 +
 18.2173 +  return res;
 18.2174 +}
 18.2175 +
 18.2176 +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
 18.2177 +    ISzAlloc *alloc, ISzAlloc *allocBig)
 18.2178 +{
 18.2179 +  CLzmaEnc *p = (CLzmaEnc *)pp;
 18.2180 +  SRes res = SZ_OK;
 18.2181 +
 18.2182 +  #ifdef COMPRESS_MF_MT
 18.2183 +  Byte allocaDummy[0x300];
 18.2184 +  int i = 0;
 18.2185 +  for (i = 0; i < 16; i++)
 18.2186 +    allocaDummy[i] = (Byte)i;
 18.2187 +  #endif
 18.2188 +
 18.2189 +  RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig));
 18.2190 +
 18.2191 +  for (;;)
 18.2192 +  {
 18.2193 +    res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
 18.2194 +    if (res != SZ_OK || p->finished != 0)
 18.2195 +      break;
 18.2196 +    if (progress != 0)
 18.2197 +    {
 18.2198 +      res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
 18.2199 +      if (res != SZ_OK)
 18.2200 +      {
 18.2201 +        res = SZ_ERROR_PROGRESS;
 18.2202 +        break;
 18.2203 +      }
 18.2204 +    }
 18.2205 +  }
 18.2206 +  LzmaEnc_Finish(pp);
 18.2207 +  return res;
 18.2208 +}
 18.2209 +
 18.2210 +SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
 18.2211 +{
 18.2212 +  CLzmaEnc *p = (CLzmaEnc *)pp;
 18.2213 +  int i;
 18.2214 +  UInt32 dictSize = p->dictSize;
 18.2215 +  if (*size < LZMA_PROPS_SIZE)
 18.2216 +    return SZ_ERROR_PARAM;
 18.2217 +  *size = LZMA_PROPS_SIZE;
 18.2218 +  props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
 18.2219 +
 18.2220 +  for (i = 11; i <= 30; i++)
 18.2221 +  {
 18.2222 +    if (dictSize <= ((UInt32)2 << i))
 18.2223 +    {
 18.2224 +      dictSize = (2 << i);
 18.2225 +      break;
 18.2226 +    }
 18.2227 +    if (dictSize <= ((UInt32)3 << i))
 18.2228 +    {
 18.2229 +      dictSize = (3 << i);
 18.2230 +      break;
 18.2231 +    }
 18.2232 +  }
 18.2233 +
 18.2234 +  for (i = 0; i < 4; i++)
 18.2235 +    props[1 + i] = (Byte)(dictSize >> (8 * i));
 18.2236 +  return SZ_OK;
 18.2237 +}
 18.2238 +
 18.2239 +SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
 18.2240 +    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
 18.2241 +{
 18.2242 +  SRes res;
 18.2243 +  CLzmaEnc *p = (CLzmaEnc *)pp;
 18.2244 +
 18.2245 +  CSeqOutStreamBuf outStream;
 18.2246 +
 18.2247 +  LzmaEnc_SetInputBuf(p, src, srcLen);
 18.2248 +
 18.2249 +  outStream.funcTable.Write = MyWrite;
 18.2250 +  outStream.data = dest;
 18.2251 +  outStream.rem = *destLen;
 18.2252 +  outStream.overflow = False;
 18.2253 +
 18.2254 +  p->writeEndMark = writeEndMark;
 18.2255 +  res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable,
 18.2256 +      progress, alloc, allocBig);
 18.2257 +
 18.2258 +  *destLen -= outStream.rem;
 18.2259 +  if (outStream.overflow)
 18.2260 +    return SZ_ERROR_OUTPUT_EOF;
 18.2261 +  return res;
 18.2262 +}
 18.2263 +
 18.2264 +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
 18.2265 +    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
 18.2266 +    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
 18.2267 +{
 18.2268 +  CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
 18.2269 +  SRes res;
 18.2270 +  if (p == 0)
 18.2271 +    return SZ_ERROR_MEM;
 18.2272 +
 18.2273 +  res = LzmaEnc_SetProps(p, props);
 18.2274 +  if (res == SZ_OK)
 18.2275 +  {
 18.2276 +    res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
 18.2277 +    if (res == SZ_OK)
 18.2278 +      res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
 18.2279 +          writeEndMark, progress, alloc, allocBig);
 18.2280 +  }
 18.2281 +
 18.2282 +  LzmaEnc_Destroy(p, alloc, allocBig);
 18.2283 +  return res;
 18.2284 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/libs/openctm/liblzma/LzmaEnc.h	Thu Sep 26 04:47:05 2013 +0300
    19.3 @@ -0,0 +1,72 @@
    19.4 +/*  LzmaEnc.h -- LZMA Encoder
    19.5 +2008-10-04 : Igor Pavlov : Public domain */
    19.6 +
    19.7 +#ifndef __LZMAENC_H
    19.8 +#define __LZMAENC_H
    19.9 +
   19.10 +#include "Types.h"
   19.11 +
   19.12 +#define LZMA_PROPS_SIZE 5
   19.13 +
   19.14 +typedef struct _CLzmaEncProps
   19.15 +{
   19.16 +  int level;       /*  0 <= level <= 9 */
   19.17 +  UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
   19.18 +                      (1 << 12) <= dictSize <= (1 << 30) for 64-bit version
   19.19 +                       default = (1 << 24) */
   19.20 +  int lc;          /* 0 <= lc <= 8, default = 3 */
   19.21 +  int lp;          /* 0 <= lp <= 4, default = 0 */
   19.22 +  int pb;          /* 0 <= pb <= 4, default = 2 */
   19.23 +  int algo;        /* 0 - fast, 1 - normal, default = 1 */
   19.24 +  int fb;          /* 5 <= fb <= 273, default = 32 */
   19.25 +  int btMode;      /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
   19.26 +  int numHashBytes; /* 2, 3 or 4, default = 4 */
   19.27 +  UInt32 mc;        /* 1 <= mc <= (1 << 30), default = 32 */
   19.28 +  unsigned writeEndMark;  /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
   19.29 +  int numThreads;  /* 1 or 2, default = 2 */
   19.30 +} CLzmaEncProps;
   19.31 +
   19.32 +void LzmaEncProps_Init(CLzmaEncProps *p);
   19.33 +void LzmaEncProps_Normalize(CLzmaEncProps *p);
   19.34 +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
   19.35 +
   19.36 +
   19.37 +/* ---------- CLzmaEncHandle Interface ---------- */
   19.38 +
   19.39 +/* LzmaEnc_* functions can return the following exit codes:
   19.40 +Returns:
   19.41 +  SZ_OK           - OK
   19.42 +  SZ_ERROR_MEM    - Memory allocation error
   19.43 +  SZ_ERROR_PARAM  - Incorrect paramater in props
   19.44 +  SZ_ERROR_WRITE  - Write callback error.
   19.45 +  SZ_ERROR_PROGRESS - some break from progress callback
   19.46 +  SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
   19.47 +*/
   19.48 +
   19.49 +typedef void * CLzmaEncHandle;
   19.50 +
   19.51 +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
   19.52 +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
   19.53 +SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
   19.54 +SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
   19.55 +SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
   19.56 +    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
   19.57 +SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
   19.58 +    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
   19.59 +
   19.60 +/* ---------- One Call Interface ---------- */
   19.61 +
   19.62 +/* LzmaEncode
   19.63 +Return code:
   19.64 +  SZ_OK               - OK
   19.65 +  SZ_ERROR_MEM        - Memory allocation error
   19.66 +  SZ_ERROR_PARAM      - Incorrect paramater
   19.67 +  SZ_ERROR_OUTPUT_EOF - output buffer overflow
   19.68 +  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)
   19.69 +*/
   19.70 +
   19.71 +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
   19.72 +    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
   19.73 +    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
   19.74 +
   19.75 +#endif
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/libs/openctm/liblzma/LzmaLib.c	Thu Sep 26 04:47:05 2013 +0300
    20.3 @@ -0,0 +1,48 @@
    20.4 +/* LzmaLib.c -- LZMA library wrapper
    20.5 +2008-08-05
    20.6 +Igor Pavlov
    20.7 +Public domain */
    20.8 +
    20.9 +#include "LzmaEnc.h"
   20.10 +#include "LzmaDec.h"
   20.11 +#include "Alloc.h"
   20.12 +#include "LzmaLib.h"
   20.13 +
   20.14 +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
   20.15 +static void SzFree(void *p, void *address) { p = p; MyFree(address); }
   20.16 +static ISzAlloc g_Alloc = { SzAlloc, SzFree };
   20.17 +
   20.18 +MY_STDAPI LzmaCompress(unsigned char *dest, size_t  *destLen, const unsigned char *src, size_t  srcLen,
   20.19 +  unsigned char *outProps, size_t *outPropsSize,
   20.20 +  int level, /* 0 <= level <= 9, default = 5 */
   20.21 +  unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */
   20.22 +  int lc, /* 0 <= lc <= 8, default = 3  */
   20.23 +  int lp, /* 0 <= lp <= 4, default = 0  */
   20.24 +  int pb, /* 0 <= pb <= 4, default = 2  */
   20.25 +  int fb,  /* 5 <= fb <= 273, default = 32 */
   20.26 +  int numThreads, /* 1 or 2, default = 2 */
   20.27 +  int algo /* 0 = fast, 1 = normal */
   20.28 +)
   20.29 +{
   20.30 +  CLzmaEncProps props;
   20.31 +  LzmaEncProps_Init(&props);
   20.32 +  props.level = level;
   20.33 +  props.dictSize = dictSize;
   20.34 +  props.lc = lc;
   20.35 +  props.lp = lp;
   20.36 +  props.pb = pb;
   20.37 +  props.fb = fb;
   20.38 +  props.numThreads = numThreads;
   20.39 +  props.algo = algo;
   20.40 +
   20.41 +  return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0,
   20.42 +      NULL, &g_Alloc, &g_Alloc);
   20.43 +}
   20.44 +
   20.45 +
   20.46 +MY_STDAPI LzmaUncompress(unsigned char *dest, size_t  *destLen, const unsigned char *src, size_t  *srcLen,
   20.47 +  const unsigned char *props, size_t propsSize)
   20.48 +{
   20.49 +  ELzmaStatus status;
   20.50 +  return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc);
   20.51 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/libs/openctm/liblzma/LzmaLib.h	Thu Sep 26 04:47:05 2013 +0300
    21.3 @@ -0,0 +1,136 @@
    21.4 +/* LzmaLib.h -- LZMA library interface
    21.5 +2008-08-05
    21.6 +Igor Pavlov
    21.7 +Public domain */
    21.8 +
    21.9 +#ifndef __LZMALIB_H
   21.10 +#define __LZMALIB_H
   21.11 +
   21.12 +#include "Types.h"
   21.13 +
   21.14 +#ifdef __cplusplus
   21.15 +  #define MY_EXTERN_C extern "C"
   21.16 +#else
   21.17 +  #define MY_EXTERN_C extern
   21.18 +#endif
   21.19 +
   21.20 +#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL
   21.21 +
   21.22 +#define LZMA_PROPS_SIZE 5
   21.23 +
   21.24 +/*
   21.25 +RAM requirements for LZMA:
   21.26 +  for compression:   (dictSize * 11.5 + 6 MB) + state_size
   21.27 +  for decompression: dictSize + state_size
   21.28 +    state_size = (4 + (1.5 << (lc + lp))) KB
   21.29 +    by default (lc=3, lp=0), state_size = 16 KB.
   21.30 +
   21.31 +LZMA properties (5 bytes) format
   21.32 +    Offset Size  Description
   21.33 +      0     1    lc, lp and pb in encoded form.
   21.34 +      1     4    dictSize (little endian).
   21.35 +*/
   21.36 +
   21.37 +/*
   21.38 +LzmaCompress
   21.39 +------------
   21.40 +
   21.41 +outPropsSize -
   21.42 +     In:  the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.
   21.43 +     Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.
   21.44 +
   21.45 +  LZMA Encoder will use defult values for any parameter, if it is
   21.46 +  -1  for any from: level, loc, lp, pb, fb, numThreads
   21.47 +   0  for dictSize
   21.48 +  
   21.49 +level - compression level: 0 <= level <= 9;
   21.50 +
   21.51 +  level dictSize algo  fb
   21.52 +    0:    16 KB   0    32
   21.53 +    1:    64 KB   0    32
   21.54 +    2:   256 KB   0    32
   21.55 +    3:     1 MB   0    32
   21.56 +    4:     4 MB   0    32
   21.57 +    5:    16 MB   1    32
   21.58 +    6:    32 MB   1    32
   21.59 +    7+:   64 MB   1    64
   21.60 + 
   21.61 +  The default value for "level" is 5.
   21.62 +
   21.63 +  algo = 0 means fast method
   21.64 +  algo = 1 means normal method
   21.65 +
   21.66 +dictSize - The dictionary size in bytes. The maximum value is
   21.67 +        128 MB = (1 << 27) bytes for 32-bit version
   21.68 +          1 GB = (1 << 30) bytes for 64-bit version
   21.69 +     The default value is 16 MB = (1 << 24) bytes.
   21.70 +     It's recommended to use the dictionary that is larger than 4 KB and
   21.71 +     that can be calculated as (1 << N) or (3 << N) sizes.
   21.72 +
   21.73 +lc - The number of literal context bits (high bits of previous literal).
   21.74 +     It can be in the range from 0 to 8. The default value is 3.
   21.75 +     Sometimes lc=4 gives the gain for big files.
   21.76 +
   21.77 +lp - The number of literal pos bits (low bits of current position for literals).
   21.78 +     It can be in the range from 0 to 4. The default value is 0.
   21.79 +     The lp switch is intended for periodical data when the period is equal to 2^lp.
   21.80 +     For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's
   21.81 +     better to set lc=0, if you change lp switch.
   21.82 +
   21.83 +pb - The number of pos bits (low bits of current position).
   21.84 +     It can be in the range from 0 to 4. The default value is 2.
   21.85 +     The pb switch is intended for periodical data when the period is equal 2^pb.
   21.86 +
   21.87 +fb - Word size (the number of fast bytes).
   21.88 +     It can be in the range from 5 to 273. The default value is 32.
   21.89 +     Usually, a big number gives a little bit better compression ratio and
   21.90 +     slower compression process.
   21.91 +
   21.92 +numThreads - The number of thereads. 1 or 2. The default value is 2.
   21.93 +     Fast mode (algo = 0) can use only 1 thread.
   21.94 +
   21.95 +Out:
   21.96 +  destLen  - processed output size
   21.97 +Returns:
   21.98 +  SZ_OK               - OK
   21.99 +  SZ_ERROR_MEM        - Memory allocation error
  21.100 +  SZ_ERROR_PARAM      - Incorrect paramater
  21.101 +  SZ_ERROR_OUTPUT_EOF - output buffer overflow
  21.102 +  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)
  21.103 +*/
  21.104 +
  21.105 +MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
  21.106 +  unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */
  21.107 +  int level,      /* 0 <= level <= 9, default = 5 */
  21.108 +  unsigned dictSize,  /* default = (1 << 24) */
  21.109 +  int lc,         /* 0 <= lc <= 8, default = 3  */
  21.110 +  int lp,         /* 0 <= lp <= 4, default = 0  */
  21.111 +  int pb,         /* 0 <= pb <= 4, default = 2  */
  21.112 +  int fb,         /* 5 <= fb <= 273, default = 32 */
  21.113 +  int numThreads, /* 1 or 2, default = 2 */
  21.114 +  int algo        /* 0 = fast, 1 = normal, default = 0 for level < 5, 1 for level >= 5 */
  21.115 +  );
  21.116 +
  21.117 +/*
  21.118 +LzmaUncompress
  21.119 +--------------
  21.120 +In:
  21.121 +  dest     - output data
  21.122 +  destLen  - output data size
  21.123 +  src      - input data
  21.124 +  srcLen   - input data size
  21.125 +Out:
  21.126 +  destLen  - processed output size
  21.127 +  srcLen   - processed input size
  21.128 +Returns:
  21.129 +  SZ_OK                - OK
  21.130 +  SZ_ERROR_DATA        - Data error
  21.131 +  SZ_ERROR_MEM         - Memory allocation arror
  21.132 +  SZ_ERROR_UNSUPPORTED - Unsupported properties
  21.133 +  SZ_ERROR_INPUT_EOF   - it needs more bytes in input buffer (src)
  21.134 +*/
  21.135 +
  21.136 +MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
  21.137 +  const unsigned char *props, size_t propsSize);
  21.138 +
  21.139 +#endif
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/libs/openctm/liblzma/NameMangle.h	Thu Sep 26 04:47:05 2013 +0300
    22.3 @@ -0,0 +1,84 @@
    22.4 +/* NameMangle.h -- Name mangling to avoid linking conflicts
    22.5 +2009-04-15 : Marcus Geelnard : Public domain */
    22.6 +
    22.7 +#ifndef __7Z_NAMEMANGLE_H
    22.8 +#define __7Z_NAMEMANGLE_H
    22.9 +
   22.10 +#ifdef LZMA_PREFIX_CTM
   22.11 +
   22.12 +/* Alloc.c */
   22.13 +#define MyAlloc _ctm_MyAlloc
   22.14 +#define MyFree _ctm_MyFree
   22.15 +#ifdef _WIN32
   22.16 +#define MidAlloc _ctm_MidAlloc
   22.17 +#define MidFree _ctm_MidFree
   22.18 +#define SetLargePageSize _ctm_SetLargePageSize
   22.19 +#define BigAlloc _ctm_BigAlloc
   22.20 +#define BigFree _ctm_BigFree
   22.21 +#endif /* _WIN32 */
   22.22 +
   22.23 +/* LzFind.c */
   22.24 +#define MatchFinder_GetPointerToCurrentPos _ctm_MatchFinder_GetPointerToCurrentPos
   22.25 +#define MatchFinder_GetIndexByte _ctm_MatchFinder_GetIndexByte
   22.26 +#define MatchFinder_GetNumAvailableBytes _ctm_MatchFinder_GetNumAvailableBytes
   22.27 +#define MatchFinder_ReduceOffsets _ctm_MatchFinder_ReduceOffsets
   22.28 +#define MatchFinder_MoveBlock _ctm_MatchFinder_MoveBlock
   22.29 +#define MatchFinder_NeedMove _ctm_MatchFinder_NeedMove
   22.30 +#define MatchFinder_ReadIfRequired _ctm_MatchFinder_ReadIfRequired
   22.31 +#define MatchFinder_Construct _ctm_MatchFinder_Construct
   22.32 +#define MatchFinder_Free _ctm_MatchFinder_Free
   22.33 +#define MatchFinder_Create _ctm_MatchFinder_Create
   22.34 +#define MatchFinder_Init _ctm_MatchFinder_Init
   22.35 +#define MatchFinder_Normalize3 _ctm_MatchFinder_Normalize3
   22.36 +#define GetMatchesSpec1 _ctm_GetMatchesSpec1
   22.37 +#define Bt3Zip_MatchFinder_GetMatches _ctm_Bt3Zip_MatchFinder_GetMatches
   22.38 +#define Hc3Zip_MatchFinder_GetMatches _ctm_Hc3Zip_MatchFinder_GetMatches
   22.39 +#define Bt3Zip_MatchFinder_Skip _ctm_Bt3Zip_MatchFinder_Skip
   22.40 +#define Hc3Zip_MatchFinder_Skip _ctm_Hc3Zip_MatchFinder_Skip
   22.41 +#define MatchFinder_CreateVTable _ctm_MatchFinder_CreateVTable
   22.42 +
   22.43 +/* LzmaDec.c */
   22.44 +#define LzmaDec_InitDicAndState _ctm_LzmaDec_InitDicAndState
   22.45 +#define LzmaDec_Init _ctm_LzmaDec_Init
   22.46 +#define LzmaDec_DecodeToDic _ctm_LzmaDec_DecodeToDic
   22.47 +#define LzmaDec_DecodeToBuf _ctm_LzmaDec_DecodeToBuf
   22.48 +#define LzmaDec_FreeProbs _ctm_LzmaDec_FreeProbs
   22.49 +#define LzmaDec_Free _ctm_LzmaDec_Free
   22.50 +#define LzmaProps_Decode _ctm_LzmaProps_Decode
   22.51 +#define LzmaDec_AllocateProbs _ctm_LzmaDec_AllocateProbs
   22.52 +#define LzmaDec_Allocate _ctm_LzmaDec_Allocate
   22.53 +#define LzmaDecode _ctm_LzmaDecode
   22.54 +
   22.55 +/* LzmaEnc.c */
   22.56 +#define LzmaEncProps_Init _ctm_LzmaEncProps_Init
   22.57 +#define LzmaEncProps_Normalize _ctm_LzmaEncProps_Normalize
   22.58 +#define LzmaEncProps_GetDictSize _ctm_LzmaEncProps_GetDictSize
   22.59 +#define LzmaEnc_FastPosInit _ctm_LzmaEnc_FastPosInit
   22.60 +#define LzmaEnc_SaveState _ctm_LzmaEnc_SaveState
   22.61 +#define LzmaEnc_RestoreState _ctm_LzmaEnc_RestoreState
   22.62 +#define LzmaEnc_SetProps _ctm_LzmaEnc_SetProps
   22.63 +#define LzmaEnc_InitPriceTables _ctm_LzmaEnc_InitPriceTables
   22.64 +#define LzmaEnc_Construct _ctm_LzmaEnc_Construct
   22.65 +#define LzmaEnc_Create _ctm_LzmaEnc_Create
   22.66 +#define LzmaEnc_FreeLits _ctm_LzmaEnc_FreeLits
   22.67 +#define LzmaEnc_Destruct _ctm_LzmaEnc_Destruct
   22.68 +#define LzmaEnc_Destroy _ctm_LzmaEnc_Destroy
   22.69 +#define LzmaEnc_Init _ctm_LzmaEnc_Init
   22.70 +#define LzmaEnc_InitPrices _ctm_LzmaEnc_InitPrices
   22.71 +#define LzmaEnc_PrepareForLzma2 _ctm_LzmaEnc_PrepareForLzma2
   22.72 +#define LzmaEnc_MemPrepare _ctm_LzmaEnc_MemPrepare
   22.73 +#define LzmaEnc_Finish _ctm_LzmaEnc_Finish
   22.74 +#define LzmaEnc_GetNumAvailableBytes _ctm_LzmaEnc_GetNumAvailableBytes
   22.75 +#define LzmaEnc_GetCurBuf _ctm_LzmaEnc_GetCurBuf
   22.76 +#define LzmaEnc_CodeOneMemBlock _ctm_LzmaEnc_CodeOneMemBlock
   22.77 +#define LzmaEnc_Encode _ctm_LzmaEnc_Encode
   22.78 +#define LzmaEnc_WriteProperties _ctm_LzmaEnc_WriteProperties
   22.79 +#define LzmaEnc_MemEncode _ctm_LzmaEnc_MemEncode
   22.80 +
   22.81 +/* LzmaLib.c */
   22.82 +#define LzmaCompress _ctm_LzmaCompress
   22.83 +#define LzmaUncompress _ctm_LzmaUncompress
   22.84 +
   22.85 +#endif /* LZMA_PREFIX_CTM */
   22.86 +
   22.87 +#endif /* __7Z_NAMEMANGLE_H */
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/libs/openctm/liblzma/Types.h	Thu Sep 26 04:47:05 2013 +0300
    23.3 @@ -0,0 +1,210 @@
    23.4 +/* Types.h -- Basic types
    23.5 +2008-11-23 : Igor Pavlov : Public domain */
    23.6 +
    23.7 +#ifndef __7Z_TYPES_H
    23.8 +#define __7Z_TYPES_H
    23.9 +
   23.10 +#include <stddef.h>
   23.11 +
   23.12 +#ifdef _WIN32
   23.13 +#include <windows.h>
   23.14 +#endif
   23.15 +
   23.16 +#include "NameMangle.h"
   23.17 +
   23.18 +#define SZ_OK 0
   23.19 +
   23.20 +#define SZ_ERROR_DATA 1
   23.21 +#define SZ_ERROR_MEM 2
   23.22 +#define SZ_ERROR_CRC 3
   23.23 +#define SZ_ERROR_UNSUPPORTED 4
   23.24 +#define SZ_ERROR_PARAM 5
   23.25 +#define SZ_ERROR_INPUT_EOF 6
   23.26 +#define SZ_ERROR_OUTPUT_EOF 7
   23.27 +#define SZ_ERROR_READ 8
   23.28 +#define SZ_ERROR_WRITE 9
   23.29 +#define SZ_ERROR_PROGRESS 10
   23.30 +#define SZ_ERROR_FAIL 11
   23.31 +#define SZ_ERROR_THREAD 12
   23.32 +
   23.33 +#define SZ_ERROR_ARCHIVE 16
   23.34 +#define SZ_ERROR_NO_ARCHIVE 17
   23.35 +
   23.36 +typedef int SRes;
   23.37 +
   23.38 +#ifdef _WIN32
   23.39 +typedef DWORD WRes;
   23.40 +#else
   23.41 +typedef int WRes;
   23.42 +#endif
   23.43 +
   23.44 +#ifndef RINOK
   23.45 +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
   23.46 +#endif
   23.47 +
   23.48 +typedef unsigned char Byte;
   23.49 +typedef short Int16;
   23.50 +typedef unsigned short UInt16;
   23.51 +
   23.52 +#ifdef _LZMA_UINT32_IS_ULONG
   23.53 +typedef long Int32;
   23.54 +typedef unsigned long UInt32;
   23.55 +#else
   23.56 +typedef int Int32;
   23.57 +typedef unsigned int UInt32;
   23.58 +#endif
   23.59 +
   23.60 +#ifdef _SZ_NO_INT_64
   23.61 +
   23.62 +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
   23.63 +   NOTES: Some code will work incorrectly in that case! */
   23.64 +
   23.65 +typedef long Int64;
   23.66 +typedef unsigned long UInt64;
   23.67 +
   23.68 +#else
   23.69 +
   23.70 +#if defined(_MSC_VER) || defined(__BORLANDC__)
   23.71 +typedef __int64 Int64;
   23.72 +typedef unsigned __int64 UInt64;
   23.73 +#else
   23.74 +typedef long long int Int64;
   23.75 +typedef unsigned long long int UInt64;
   23.76 +#endif
   23.77 +
   23.78 +#endif
   23.79 +
   23.80 +#ifdef _LZMA_NO_SYSTEM_SIZE_T
   23.81 +typedef UInt32 SizeT;
   23.82 +#else
   23.83 +typedef size_t SizeT;
   23.84 +#endif
   23.85 +
   23.86 +typedef int Bool;
   23.87 +#define True 1
   23.88 +#define False 0
   23.89 +
   23.90 +
   23.91 +#ifdef _MSC_VER
   23.92 +
   23.93 +#if _MSC_VER >= 1300
   23.94 +#define MY_NO_INLINE __declspec(noinline)
   23.95 +#else
   23.96 +#define MY_NO_INLINE
   23.97 +#endif
   23.98 +
   23.99 +#define MY_CDECL __cdecl
  23.100 +#define MY_STD_CALL __stdcall
  23.101 +#define MY_FAST_CALL MY_NO_INLINE __fastcall
  23.102 +
  23.103 +#else
  23.104 +
  23.105 +#define MY_CDECL
  23.106 +#define MY_STD_CALL
  23.107 +#define MY_FAST_CALL
  23.108 +
  23.109 +#endif
  23.110 +
  23.111 +
  23.112 +/* The following interfaces use first parameter as pointer to structure */
  23.113 +
  23.114 +typedef struct
  23.115 +{
  23.116 +  SRes (*Read)(void *p, void *buf, size_t *size);
  23.117 +    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
  23.118 +       (output(*size) < input(*size)) is allowed */
  23.119 +} ISeqInStream;
  23.120 +
  23.121 +/* it can return SZ_ERROR_INPUT_EOF */
  23.122 +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
  23.123 +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
  23.124 +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
  23.125 +
  23.126 +typedef struct
  23.127 +{
  23.128 +  size_t (*Write)(void *p, const void *buf, size_t size);
  23.129 +    /* Returns: result - the number of actually written bytes.
  23.130 +       (result < size) means error */
  23.131 +} ISeqOutStream;
  23.132 +
  23.133 +typedef enum
  23.134 +{
  23.135 +  SZ_SEEK_SET = 0,
  23.136 +  SZ_SEEK_CUR = 1,
  23.137 +  SZ_SEEK_END = 2
  23.138 +} ESzSeek;
  23.139 +
  23.140 +typedef struct
  23.141 +{
  23.142 +  SRes (*Read)(void *p, void *buf, size_t *size);  /* same as ISeqInStream::Read */
  23.143 +  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
  23.144 +} ISeekInStream;
  23.145 +
  23.146 +typedef struct
  23.147 +{
  23.148 +  SRes (*Look)(void *p, void **buf, size_t *size);
  23.149 +    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
  23.150 +       (output(*size) > input(*size)) is not allowed
  23.151 +       (output(*size) < input(*size)) is allowed */
  23.152 +  SRes (*Skip)(void *p, size_t offset);
  23.153 +    /* offset must be <= output(*size) of Look */
  23.154 +
  23.155 +  SRes (*Read)(void *p, void *buf, size_t *size);
  23.156 +    /* reads directly (without buffer). It's same as ISeqInStream::Read */
  23.157 +  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
  23.158 +} ILookInStream;
  23.159 +
  23.160 +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
  23.161 +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
  23.162 +
  23.163 +/* reads via ILookInStream::Read */
  23.164 +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
  23.165 +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
  23.166 +
  23.167 +#define LookToRead_BUF_SIZE (1 << 14)
  23.168 +
  23.169 +typedef struct
  23.170 +{
  23.171 +  ILookInStream s;
  23.172 +  ISeekInStream *realStream;
  23.173 +  size_t pos;
  23.174 +  size_t size;
  23.175 +  Byte buf[LookToRead_BUF_SIZE];
  23.176 +} CLookToRead;
  23.177 +
  23.178 +void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
  23.179 +void LookToRead_Init(CLookToRead *p);
  23.180 +
  23.181 +typedef struct
  23.182 +{
  23.183 +  ISeqInStream s;
  23.184 +  ILookInStream *realStream;
  23.185 +} CSecToLook;
  23.186 +
  23.187 +void SecToLook_CreateVTable(CSecToLook *p);
  23.188 +
  23.189 +typedef struct
  23.190 +{
  23.191 +  ISeqInStream s;
  23.192 +  ILookInStream *realStream;
  23.193 +} CSecToRead;
  23.194 +
  23.195 +void SecToRead_CreateVTable(CSecToRead *p);
  23.196 +
  23.197 +typedef struct
  23.198 +{
  23.199 +  SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
  23.200 +    /* Returns: result. (result != SZ_OK) means break.
  23.201 +       Value (UInt64)(Int64)-1 for size means unknown value. */
  23.202 +} ICompressProgress;
  23.203 +
  23.204 +typedef struct
  23.205 +{
  23.206 +  void *(*Alloc)(void *p, size_t size);
  23.207 +  void (*Free)(void *p, void *address); /* address can be 0 */
  23.208 +} ISzAlloc;
  23.209 +
  23.210 +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
  23.211 +#define IAlloc_Free(p, a) (p)->Free((p), a)
  23.212 +
  23.213 +#endif
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/libs/openctm/liblzma/readme.txt	Thu Sep 26 04:47:05 2013 +0300
    24.3 @@ -0,0 +1,7 @@
    24.4 +This is the C library implementation of LZMA compression/decompression by Igor Pavlov.
    24.5 +
    24.6 +Author:  Igor Pavlov
    24.7 +License: Public domain
    24.8 +Version: 4.65 (2009-02-03)
    24.9 +
   24.10 +Some administrative adaptations for integration in OpenCTM were made by Marcus Geelnard.
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/libs/openctm/openctm.c	Thu Sep 26 04:47:05 2013 +0300
    25.3 @@ -0,0 +1,1423 @@
    25.4 +//-----------------------------------------------------------------------------
    25.5 +// Product:     OpenCTM
    25.6 +// File:        openctm.c
    25.7 +// Description: API functions.
    25.8 +//-----------------------------------------------------------------------------
    25.9 +// Copyright (c) 2009-2010 Marcus Geelnard
   25.10 +//
   25.11 +// This software is provided 'as-is', without any express or implied
   25.12 +// warranty. In no event will the authors be held liable for any damages
   25.13 +// arising from the use of this software.
   25.14 +//
   25.15 +// Permission is granted to anyone to use this software for any purpose,
   25.16 +// including commercial applications, and to alter it and redistribute it
   25.17 +// freely, subject to the following restrictions:
   25.18 +//
   25.19 +//     1. The origin of this software must not be misrepresented; you must not
   25.20 +//     claim that you wrote the original software. If you use this software
   25.21 +//     in a product, an acknowledgment in the product documentation would be
   25.22 +//     appreciated but is not required.
   25.23 +//
   25.24 +//     2. Altered source versions must be plainly marked as such, and must not
   25.25 +//     be misrepresented as being the original software.
   25.26 +//
   25.27 +//     3. This notice may not be removed or altered from any source
   25.28 +//     distribution.
   25.29 +//-----------------------------------------------------------------------------
   25.30 +
   25.31 +#include <stdlib.h>
   25.32 +#include <string.h>
   25.33 +#include <stdio.h>
   25.34 +#include <math.h>
   25.35 +#include "openctm.h"
   25.36 +#include "internal.h"
   25.37 +
   25.38 +
   25.39 +// The C99 macro isfinite() is not supported on all platforms (specifically,
   25.40 +// MS Visual Studio does not support C99)
   25.41 +#if !defined(isfinite) && defined(_MSC_VER)
   25.42 +  #include <float.h>
   25.43 +  #define isfinite(x) _finite(x)
   25.44 +#endif
   25.45 +
   25.46 +
   25.47 +//-----------------------------------------------------------------------------
   25.48 +// _ctmFreeMapList() - Free a float map list.
   25.49 +//-----------------------------------------------------------------------------
   25.50 +static void _ctmFreeMapList(_CTMcontext * self, _CTMfloatmap * aMapList)
   25.51 +{
   25.52 +  _CTMfloatmap * map, * nextMap;
   25.53 +  map = aMapList;
   25.54 +  while(map)
   25.55 +  {
   25.56 +    // Free internally allocated array (if we are in import mode)
   25.57 +    if((self->mMode == CTM_IMPORT) && map->mValues)
   25.58 +      free(map->mValues);
   25.59 +
   25.60 +    // Free map name
   25.61 +    if(map->mName)
   25.62 +      free(map->mName);
   25.63 +
   25.64 +    // Free file name
   25.65 +    if(map->mFileName)
   25.66 +      free(map->mFileName);
   25.67 +
   25.68 +    nextMap = map->mNext;
   25.69 +    free(map);
   25.70 +    map = nextMap;
   25.71 +  }
   25.72 +}
   25.73 +
   25.74 +//-----------------------------------------------------------------------------
   25.75 +// _ctmClearMesh() - Clear the mesh in a CTM context.
   25.76 +//-----------------------------------------------------------------------------
   25.77 +static void _ctmClearMesh(_CTMcontext * self)
   25.78 +{
   25.79 +  // Free internally allocated mesh arrays
   25.80 +  if(self->mMode == CTM_IMPORT)
   25.81 +  {
   25.82 +    if(self->mVertices)
   25.83 +      free(self->mVertices);
   25.84 +    if(self->mIndices)
   25.85 +      free(self->mIndices);
   25.86 +    if(self->mNormals)
   25.87 +      free(self->mNormals);
   25.88 +  }
   25.89 +
   25.90 +  // Clear externally assigned mesh arrays
   25.91 +  self->mVertices = (CTMfloat *) 0;
   25.92 +  self->mVertexCount = 0;
   25.93 +  self->mIndices = (CTMuint *) 0;
   25.94 +  self->mTriangleCount = 0;
   25.95 +  self->mNormals = (CTMfloat *) 0;
   25.96 +
   25.97 +  // Free UV coordinate map list
   25.98 +  _ctmFreeMapList(self, self->mUVMaps);
   25.99 +  self->mUVMaps = (_CTMfloatmap *) 0;
  25.100 +  self->mUVMapCount = 0;
  25.101 +
  25.102 +  // Free attribute map list
  25.103 +  _ctmFreeMapList(self, self->mAttribMaps);
  25.104 +  self->mAttribMaps = (_CTMfloatmap *) 0;
  25.105 +  self->mAttribMapCount = 0;
  25.106 +}
  25.107 +
  25.108 +//-----------------------------------------------------------------------------
  25.109 +// _ctmCheckMeshIntegrity() - Check if a mesh is valid (i.e. is non-empty, and
  25.110 +// contains valid data).
  25.111 +//-----------------------------------------------------------------------------
  25.112 +
  25.113 +static CTMint _ctmCheckMeshIntegrity(_CTMcontext * self)
  25.114 +{
  25.115 +  CTMuint i;
  25.116 +  _CTMfloatmap * map;
  25.117 +
  25.118 +  // Check that we have all the mandatory data
  25.119 +  if(!self->mVertices || !self->mIndices || (self->mVertexCount < 1) ||
  25.120 +     (self->mTriangleCount < 1))
  25.121 +  {
  25.122 +    return CTM_FALSE;
  25.123 +  }
  25.124 +
  25.125 +  // Check that all indices are within range
  25.126 +  for(i = 0; i < (self->mTriangleCount * 3); ++ i)
  25.127 +  {
  25.128 +    if(self->mIndices[i] >= self->mVertexCount)
  25.129 +    {
  25.130 +      return CTM_FALSE;
  25.131 +    }
  25.132 +  }
  25.133 +
  25.134 +  // Check that all vertices are finite (non-NaN, non-inf)
  25.135 +  for(i = 0; i < self->mVertexCount * 3; ++ i)
  25.136 +  {
  25.137 +    if(!isfinite(self->mVertices[i]))
  25.138 +    {
  25.139 +      return CTM_FALSE;
  25.140 +    }
  25.141 +  }
  25.142 +
  25.143 +  // Check that all normals are finite (non-NaN, non-inf)
  25.144 +  if(self->mNormals)
  25.145 +  {
  25.146 +    for(i = 0; i < self->mVertexCount * 3; ++ i)
  25.147 +    {
  25.148 +      if(!isfinite(self->mNormals[i]))
  25.149 +      {
  25.150 +        return CTM_FALSE;
  25.151 +      }
  25.152 +    }
  25.153 +  }
  25.154 +
  25.155 +  // Check that all UV maps are finite (non-NaN, non-inf)
  25.156 +  map = self->mUVMaps;
  25.157 +  while(map)
  25.158 +  {
  25.159 +    for(i = 0; i < self->mVertexCount * 2; ++ i)
  25.160 +    {
  25.161 +      if(!isfinite(map->mValues[i]))
  25.162 +      {
  25.163 +        return CTM_FALSE;
  25.164 +      }
  25.165 +    }
  25.166 +    map = map->mNext;
  25.167 +  }
  25.168 +
  25.169 +  // Check that all attribute maps are finite (non-NaN, non-inf)
  25.170 +  map = self->mAttribMaps;
  25.171 +  while(map)
  25.172 +  {
  25.173 +    for(i = 0; i < self->mVertexCount * 4; ++ i)
  25.174 +    {
  25.175 +      if(!isfinite(map->mValues[i]))
  25.176 +      {
  25.177 +        return CTM_FALSE;
  25.178 +      }
  25.179 +    }
  25.180 +    map = map->mNext;
  25.181 +  }
  25.182 +
  25.183 +  return CTM_TRUE;
  25.184 +}
  25.185 +
  25.186 +//-----------------------------------------------------------------------------
  25.187 +// ctmNewContext()
  25.188 +//-----------------------------------------------------------------------------
  25.189 +CTMEXPORT CTMcontext CTMCALL ctmNewContext(CTMenum aMode)
  25.190 +{
  25.191 +  _CTMcontext * self;
  25.192 +
  25.193 +  // Allocate memory for the new structure
  25.194 +  self = (_CTMcontext *) malloc(sizeof(_CTMcontext));
  25.195 +
  25.196 +  // Initialize structure (set null pointers and zero array lengths)
  25.197 +  memset(self, 0, sizeof(_CTMcontext));
  25.198 +  self->mMode = aMode;
  25.199 +  self->mError = CTM_NONE;
  25.200 +  self->mMethod = CTM_METHOD_MG1;
  25.201 +  self->mCompressionLevel = 1;
  25.202 +  self->mVertexPrecision = 1.0f / 1024.0f;
  25.203 +  self->mNormalPrecision = 1.0f / 256.0f;
  25.204 +
  25.205 +  return (CTMcontext) self;
  25.206 +}
  25.207 +
  25.208 +//-----------------------------------------------------------------------------
  25.209 +// ctmFreeContext()
  25.210 +//-----------------------------------------------------------------------------
  25.211 +CTMEXPORT void CTMCALL ctmFreeContext(CTMcontext aContext)
  25.212 +{
  25.213 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.214 +  if(!self) return;
  25.215 +
  25.216 +  // Free all mesh resources
  25.217 +  _ctmClearMesh(self);
  25.218 +
  25.219 +  // Free the file comment
  25.220 +  if(self->mFileComment)
  25.221 +    free(self->mFileComment);
  25.222 +
  25.223 +  // Free the context
  25.224 +  free(self);
  25.225 +}
  25.226 +
  25.227 +//-----------------------------------------------------------------------------
  25.228 +// ctmGetError()
  25.229 +//-----------------------------------------------------------------------------
  25.230 +CTMEXPORT CTMenum CTMCALL ctmGetError(CTMcontext aContext)
  25.231 +{
  25.232 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.233 +  CTMenum err;
  25.234 +
  25.235 +  if(!self) return CTM_INVALID_CONTEXT;
  25.236 +
  25.237 +  // Get error code and reset error state
  25.238 +  err = self->mError;
  25.239 +  self->mError = CTM_NONE;
  25.240 +  return err;
  25.241 +}
  25.242 +
  25.243 +//-----------------------------------------------------------------------------
  25.244 +// ctmErrorString()
  25.245 +//-----------------------------------------------------------------------------
  25.246 +CTMEXPORT const char * CTMCALL ctmErrorString(CTMenum aError)
  25.247 +{
  25.248 +  switch(aError)
  25.249 +  {
  25.250 +    case CTM_INVALID_CONTEXT:
  25.251 +      return "CTM_INVALID_CONTEXT";
  25.252 +    case CTM_INVALID_ARGUMENT:
  25.253 +      return "CTM_INVALID_ARGUMENT";
  25.254 +    case CTM_INVALID_OPERATION:
  25.255 +      return "CTM_INVALID_OPERATION";
  25.256 +    case CTM_INVALID_MESH:
  25.257 +      return "CTM_INVALID_MESH";
  25.258 +    case CTM_OUT_OF_MEMORY:
  25.259 +      return "CTM_OUT_OF_MEMORY";
  25.260 +    case CTM_FILE_ERROR:
  25.261 +      return "CTM_FILE_ERROR";
  25.262 +    case CTM_BAD_FORMAT:
  25.263 +      return "CTM_BAD_FORMAT";
  25.264 +    case CTM_LZMA_ERROR:
  25.265 +      return "CTM_LZMA_ERROR";
  25.266 +    case CTM_INTERNAL_ERROR:
  25.267 +      return "CTM_INTERNAL_ERROR";
  25.268 +    case CTM_UNSUPPORTED_FORMAT_VERSION:
  25.269 +      return "CTM_UNSUPPORTED_FORMAT_VERSION";
  25.270 +    default:
  25.271 +      return "Unknown error code";
  25.272 +  }
  25.273 +}
  25.274 +
  25.275 +//-----------------------------------------------------------------------------
  25.276 +// ctmGetInteger()
  25.277 +//-----------------------------------------------------------------------------
  25.278 +CTMEXPORT CTMuint CTMCALL ctmGetInteger(CTMcontext aContext, CTMenum aProperty)
  25.279 +{
  25.280 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.281 +  if(!self) return 0;
  25.282 +
  25.283 +  switch(aProperty)
  25.284 +  {
  25.285 +    case CTM_VERTEX_COUNT:
  25.286 +      return self->mVertexCount;
  25.287 +
  25.288 +    case CTM_TRIANGLE_COUNT:
  25.289 +      return self->mTriangleCount;
  25.290 +
  25.291 +    case CTM_UV_MAP_COUNT:
  25.292 +      return self->mUVMapCount;
  25.293 +
  25.294 +    case CTM_ATTRIB_MAP_COUNT:
  25.295 +      return self->mAttribMapCount;
  25.296 +
  25.297 +    case CTM_HAS_NORMALS:
  25.298 +      return self->mNormals ? CTM_TRUE : CTM_FALSE;
  25.299 +
  25.300 +    case CTM_COMPRESSION_METHOD:
  25.301 +      return (CTMuint) self->mMethod;
  25.302 +
  25.303 +    default:
  25.304 +      self->mError = CTM_INVALID_ARGUMENT;
  25.305 +  }
  25.306 +
  25.307 +  return 0;
  25.308 +}
  25.309 +
  25.310 +//-----------------------------------------------------------------------------
  25.311 +// ctmGetFloat()
  25.312 +//-----------------------------------------------------------------------------
  25.313 +CTMEXPORT CTMfloat CTMCALL ctmGetFloat(CTMcontext aContext, CTMenum aProperty)
  25.314 +{
  25.315 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.316 +  if(!self) return 0.0f;
  25.317 +
  25.318 +  switch(aProperty)
  25.319 +  {
  25.320 +    case CTM_VERTEX_PRECISION:
  25.321 +      return self->mVertexPrecision;
  25.322 +
  25.323 +    case CTM_NORMAL_PRECISION:
  25.324 +      return self->mNormalPrecision;
  25.325 +
  25.326 +    default:
  25.327 +      self->mError = CTM_INVALID_ARGUMENT;
  25.328 +  }
  25.329 +
  25.330 +  return 0.0f;
  25.331 +}
  25.332 +
  25.333 +//-----------------------------------------------------------------------------
  25.334 +// ctmGetIntegerArray()
  25.335 +//-----------------------------------------------------------------------------
  25.336 +CTMEXPORT const CTMuint * CTMCALL ctmGetIntegerArray(CTMcontext aContext,
  25.337 +  CTMenum aProperty)
  25.338 +{
  25.339 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.340 +  if(!self) return (CTMuint *) 0;
  25.341 +
  25.342 +  switch(aProperty)
  25.343 +  {
  25.344 +    case CTM_INDICES:
  25.345 +      return self->mIndices;
  25.346 +
  25.347 +    default:
  25.348 +      self->mError = CTM_INVALID_ARGUMENT;
  25.349 +  }
  25.350 +
  25.351 +  return (CTMuint *) 0;
  25.352 +}
  25.353 +
  25.354 +//-----------------------------------------------------------------------------
  25.355 +// ctmGetFloatArray()
  25.356 +//-----------------------------------------------------------------------------
  25.357 +CTMEXPORT const CTMfloat * CTMCALL ctmGetFloatArray(CTMcontext aContext,
  25.358 +  CTMenum aProperty)
  25.359 +{
  25.360 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.361 +  _CTMfloatmap * map;
  25.362 +  CTMuint i;
  25.363 +  if(!self) return (CTMfloat *) 0;
  25.364 +
  25.365 +  // Did the user request a UV map?
  25.366 +  if((aProperty >= CTM_UV_MAP_1) &&
  25.367 +     ((CTMuint)(aProperty - CTM_UV_MAP_1) < self->mUVMapCount))
  25.368 +  {
  25.369 +    map = self->mUVMaps;
  25.370 +    i = CTM_UV_MAP_1;
  25.371 +    while(map && (i != aProperty))
  25.372 +    {
  25.373 +      map = map->mNext;
  25.374 +      ++ i;
  25.375 +    }
  25.376 +    if(!map)
  25.377 +    {
  25.378 +      self->mError = CTM_INTERNAL_ERROR;
  25.379 +      return (CTMfloat *) 0;
  25.380 +    }
  25.381 +    return map->mValues;
  25.382 +  }
  25.383 +
  25.384 +  // Did the user request an attribute map?
  25.385 +  if((aProperty >= CTM_ATTRIB_MAP_1) &&
  25.386 +     ((CTMuint)(aProperty - CTM_ATTRIB_MAP_1) < self->mAttribMapCount))
  25.387 +  {
  25.388 +    map = self->mAttribMaps;
  25.389 +    i = CTM_ATTRIB_MAP_1;
  25.390 +    while(map && (i != aProperty))
  25.391 +    {
  25.392 +      map = map->mNext;
  25.393 +      ++ i;
  25.394 +    }
  25.395 +    if(!map)
  25.396 +    {
  25.397 +      self->mError = CTM_INTERNAL_ERROR;
  25.398 +      return (CTMfloat *) 0;
  25.399 +    }
  25.400 +    return map->mValues;
  25.401 +  }
  25.402 +
  25.403 +  switch(aProperty)
  25.404 +  {
  25.405 +    case CTM_VERTICES:
  25.406 +      return self->mVertices;
  25.407 +
  25.408 +    case CTM_NORMALS:
  25.409 +      return self->mNormals;
  25.410 +
  25.411 +    default:
  25.412 +      self->mError = CTM_INVALID_ARGUMENT;
  25.413 +  }
  25.414 +
  25.415 +  return (CTMfloat *) 0;
  25.416 +}
  25.417 +
  25.418 +//-----------------------------------------------------------------------------
  25.419 +// ctmGetNamedUVMap()
  25.420 +//-----------------------------------------------------------------------------
  25.421 +CTMEXPORT CTMenum CTMCALL ctmGetNamedUVMap(CTMcontext aContext,
  25.422 +  const char * aName)
  25.423 +{
  25.424 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.425 +  _CTMfloatmap * map;
  25.426 +  CTMuint result;
  25.427 +  if(!self) return CTM_NONE;
  25.428 +
  25.429 +  map = self->mUVMaps;
  25.430 +  result = CTM_UV_MAP_1;
  25.431 +  while(map && (strcmp(aName, map->mName) != 0))
  25.432 +  {
  25.433 +    map = map->mNext;
  25.434 +    ++ result;
  25.435 +  }
  25.436 +  if(!map)
  25.437 +  {
  25.438 +    return CTM_NONE;
  25.439 +  }
  25.440 +  return result;
  25.441 +}
  25.442 +
  25.443 +//-----------------------------------------------------------------------------
  25.444 +// ctmGetUVMapString()
  25.445 +//-----------------------------------------------------------------------------
  25.446 +CTMEXPORT const char * CTMCALL ctmGetUVMapString(CTMcontext aContext,
  25.447 +  CTMenum aUVMap, CTMenum aProperty)
  25.448 +{
  25.449 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.450 +  _CTMfloatmap * map;
  25.451 +  CTMuint i;
  25.452 +  if(!self) return (const char *) 0;
  25.453 +
  25.454 +  // Find the indicated map
  25.455 +  map = self->mUVMaps;
  25.456 +  i = CTM_UV_MAP_1;
  25.457 +  while(map && (i != aUVMap))
  25.458 +  {
  25.459 +    ++ i;
  25.460 +    map = map->mNext;
  25.461 +  }
  25.462 +  if(!map)
  25.463 +  {
  25.464 +    self->mError = CTM_INVALID_ARGUMENT;
  25.465 +    return (const char *) 0;
  25.466 +  }
  25.467 +
  25.468 +  // Get the requested string
  25.469 +  switch(aProperty)
  25.470 +  {
  25.471 +    case CTM_NAME:
  25.472 +      return (const char *) map->mName;
  25.473 +
  25.474 +    case CTM_FILE_NAME:
  25.475 +      return (const char *) map->mFileName;
  25.476 +
  25.477 +    default:
  25.478 +      self->mError = CTM_INVALID_ARGUMENT;
  25.479 +  }
  25.480 +
  25.481 +  return (const char *) 0;
  25.482 +}
  25.483 +
  25.484 +//-----------------------------------------------------------------------------
  25.485 +// ctmGetUVMapFloat()
  25.486 +//-----------------------------------------------------------------------------
  25.487 +CTMEXPORT CTMfloat CTMCALL ctmGetUVMapFloat(CTMcontext aContext,
  25.488 +  CTMenum aUVMap, CTMenum aProperty)
  25.489 +{
  25.490 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.491 +  _CTMfloatmap * map;
  25.492 +  CTMuint i;
  25.493 +  if(!self) return 0.0f;
  25.494 +
  25.495 +  // Find the indicated map
  25.496 +  map = self->mUVMaps;
  25.497 +  i = CTM_UV_MAP_1;
  25.498 +  while(map && (i != aUVMap))
  25.499 +  {
  25.500 +    ++ i;
  25.501 +    map = map->mNext;
  25.502 +  }
  25.503 +  if(!map)
  25.504 +  {
  25.505 +    self->mError = CTM_INVALID_ARGUMENT;
  25.506 +    return 0.0f;
  25.507 +  }
  25.508 +
  25.509 +  // Get the requested string
  25.510 +  switch(aProperty)
  25.511 +  {
  25.512 +    case CTM_PRECISION:
  25.513 +      return map->mPrecision;
  25.514 +
  25.515 +    default:
  25.516 +      self->mError = CTM_INVALID_ARGUMENT;
  25.517 +  }
  25.518 +
  25.519 +  return 0.0f;
  25.520 +}
  25.521 +
  25.522 +//-----------------------------------------------------------------------------
  25.523 +// ctmGetAttribMapString()
  25.524 +//-----------------------------------------------------------------------------
  25.525 +CTMEXPORT const char * CTMCALL ctmGetAttribMapString(CTMcontext aContext,
  25.526 +  CTMenum aAttribMap, CTMenum aProperty)
  25.527 +{
  25.528 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.529 +  _CTMfloatmap * map;
  25.530 +  CTMuint i;
  25.531 +  if(!self) return (const char *) 0;
  25.532 +
  25.533 +  // Find the indicated map
  25.534 +  map = self->mAttribMaps;
  25.535 +  i = CTM_ATTRIB_MAP_1;
  25.536 +  while(map && (i != aAttribMap))
  25.537 +  {
  25.538 +    ++ i;
  25.539 +    map = map->mNext;
  25.540 +  }
  25.541 +  if(!map)
  25.542 +  {
  25.543 +    self->mError = CTM_INVALID_ARGUMENT;
  25.544 +    return (const char *) 0;
  25.545 +  }
  25.546 +
  25.547 +  // Get the requested string
  25.548 +  switch(aProperty)
  25.549 +  {
  25.550 +    case CTM_NAME:
  25.551 +      return (const char *) map->mName;
  25.552 +
  25.553 +    default:
  25.554 +      self->mError = CTM_INVALID_ARGUMENT;
  25.555 +  }
  25.556 +
  25.557 +  return (const char *) 0;
  25.558 +}
  25.559 +
  25.560 +//-----------------------------------------------------------------------------
  25.561 +// ctmGetAttribMapFloat()
  25.562 +//-----------------------------------------------------------------------------
  25.563 +CTMEXPORT CTMfloat CTMCALL ctmGetAttribMapFloat(CTMcontext aContext,
  25.564 +  CTMenum aAttribMap, CTMenum aProperty)
  25.565 +{
  25.566 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.567 +  _CTMfloatmap * map;
  25.568 +  CTMuint i;
  25.569 +  if(!self) return 0.0f;
  25.570 +
  25.571 +  // Find the indicated map
  25.572 +  map = self->mAttribMaps;
  25.573 +  i = CTM_ATTRIB_MAP_1;
  25.574 +  while(map && (i != aAttribMap))
  25.575 +  {
  25.576 +    ++ i;
  25.577 +    map = map->mNext;
  25.578 +  }
  25.579 +  if(!map)
  25.580 +  {
  25.581 +    self->mError = CTM_INVALID_ARGUMENT;
  25.582 +    return 0.0f;
  25.583 +  }
  25.584 +
  25.585 +  // Get the requested string
  25.586 +  switch(aProperty)
  25.587 +  {
  25.588 +    case CTM_PRECISION:
  25.589 +      return map->mPrecision;
  25.590 +
  25.591 +    default:
  25.592 +      self->mError = CTM_INVALID_ARGUMENT;
  25.593 +  }
  25.594 +
  25.595 +  return 0.0f;
  25.596 +}
  25.597 +
  25.598 +//-----------------------------------------------------------------------------
  25.599 +// ctmGetNamedAttribMap()
  25.600 +//-----------------------------------------------------------------------------
  25.601 +CTMEXPORT CTMenum CTMCALL ctmGetNamedAttribMap(CTMcontext aContext,
  25.602 +  const char * aName)
  25.603 +{
  25.604 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.605 +  _CTMfloatmap * map;
  25.606 +  CTMuint result;
  25.607 +  if(!self) return CTM_NONE;
  25.608 +
  25.609 +  map = self->mAttribMaps;
  25.610 +  result = CTM_ATTRIB_MAP_1;
  25.611 +  while(map && (strcmp(aName, map->mName) != 0))
  25.612 +  {
  25.613 +    map = map->mNext;
  25.614 +    ++ result;
  25.615 +  }
  25.616 +  if(!map)
  25.617 +  {
  25.618 +    return CTM_NONE;
  25.619 +  }
  25.620 +  return result;
  25.621 +}
  25.622 +
  25.623 +//-----------------------------------------------------------------------------
  25.624 +// ctmGetString()
  25.625 +//-----------------------------------------------------------------------------
  25.626 +CTMEXPORT const char * CTMCALL ctmGetString(CTMcontext aContext,
  25.627 +  CTMenum aProperty)
  25.628 +{
  25.629 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.630 +  if(!self) return 0;
  25.631 +
  25.632 +  switch(aProperty)
  25.633 +  {
  25.634 +    case CTM_FILE_COMMENT:
  25.635 +      return (const char *) self->mFileComment;
  25.636 +
  25.637 +    default:
  25.638 +      self->mError = CTM_INVALID_ARGUMENT;
  25.639 +  }
  25.640 +
  25.641 +  return (const char *) 0;
  25.642 +}
  25.643 +
  25.644 +//-----------------------------------------------------------------------------
  25.645 +// ctmCompressionMethod()
  25.646 +//-----------------------------------------------------------------------------
  25.647 +CTMEXPORT void CTMCALL ctmCompressionMethod(CTMcontext aContext,
  25.648 +  CTMenum aMethod)
  25.649 +{
  25.650 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.651 +  if(!self) return;
  25.652 +
  25.653 +  // You are only allowed to change compression attributes in export mode
  25.654 +  if(self->mMode != CTM_EXPORT)
  25.655 +  {
  25.656 +    self->mError = CTM_INVALID_OPERATION;
  25.657 +    return;
  25.658 +  }
  25.659 +
  25.660 +  // Check arguments
  25.661 +  if((aMethod != CTM_METHOD_RAW) && (aMethod != CTM_METHOD_MG1) &&
  25.662 +     (aMethod != CTM_METHOD_MG2))
  25.663 +  {
  25.664 +    self->mError = CTM_INVALID_ARGUMENT;
  25.665 +    return;
  25.666 +  }
  25.667 +
  25.668 +  // Set method
  25.669 +  self->mMethod = aMethod;
  25.670 +}
  25.671 +
  25.672 +//-----------------------------------------------------------------------------
  25.673 +// ctmCompressionLevel()
  25.674 +//-----------------------------------------------------------------------------
  25.675 +CTMEXPORT void CTMCALL ctmCompressionLevel(CTMcontext aContext,
  25.676 +  CTMuint aLevel)
  25.677 +{
  25.678 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.679 +  if(!self) return;
  25.680 +
  25.681 +  // You are only allowed to change compression attributes in export mode
  25.682 +  if(self->mMode != CTM_EXPORT)
  25.683 +  {
  25.684 +    self->mError = CTM_INVALID_OPERATION;
  25.685 +    return;
  25.686 +  }
  25.687 +
  25.688 +  // Check arguments
  25.689 +  if(aLevel > 9)
  25.690 +  {
  25.691 +    self->mError = CTM_INVALID_ARGUMENT;
  25.692 +    return;
  25.693 +  }
  25.694 +
  25.695 +  // Set the compression level
  25.696 +  self->mCompressionLevel = aLevel;
  25.697 +}
  25.698 +
  25.699 +//-----------------------------------------------------------------------------
  25.700 +// ctmVertexPrecision()
  25.701 +//-----------------------------------------------------------------------------
  25.702 +CTMEXPORT void CTMCALL ctmVertexPrecision(CTMcontext aContext,
  25.703 +  CTMfloat aPrecision)
  25.704 +{
  25.705 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.706 +  if(!self) return;
  25.707 +
  25.708 +  // You are only allowed to change compression attributes in export mode
  25.709 +  if(self->mMode != CTM_EXPORT)
  25.710 +  {
  25.711 +    self->mError = CTM_INVALID_OPERATION;
  25.712 +    return;
  25.713 +  }
  25.714 +
  25.715 +  // Check arguments
  25.716 +  if(aPrecision <= 0.0f)
  25.717 +  {
  25.718 +    self->mError = CTM_INVALID_ARGUMENT;
  25.719 +    return;
  25.720 +  }
  25.721 +
  25.722 +  // Set precision
  25.723 +  self->mVertexPrecision = aPrecision;
  25.724 +}
  25.725 +
  25.726 +//-----------------------------------------------------------------------------
  25.727 +// ctmVertexPrecisionRel()
  25.728 +//-----------------------------------------------------------------------------
  25.729 +CTMEXPORT void CTMCALL ctmVertexPrecisionRel(CTMcontext aContext,
  25.730 +  CTMfloat aRelPrecision)
  25.731 +{
  25.732 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.733 +  CTMfloat avgEdgeLength, * p1, * p2;
  25.734 +  CTMuint edgeCount, i, j;
  25.735 +  if(!self) return;
  25.736 +
  25.737 +  // You are only allowed to change compression attributes in export mode
  25.738 +  if(self->mMode != CTM_EXPORT)
  25.739 +  {
  25.740 +    self->mError = CTM_INVALID_OPERATION;
  25.741 +    return;
  25.742 +  }
  25.743 +
  25.744 +  // Check arguments
  25.745 +  if(aRelPrecision <= 0.0f)
  25.746 +  {
  25.747 +    self->mError = CTM_INVALID_ARGUMENT;
  25.748 +    return;
  25.749 +  }
  25.750 +
  25.751 +  // Calculate the average edge length (Note: we actually sum up all the half-
  25.752 +  // edges, so in a proper solid mesh all connected edges are counted twice)
  25.753 +  avgEdgeLength = 0.0f;
  25.754 +  edgeCount = 0;
  25.755 +  for(i = 0; i < self->mTriangleCount; ++ i)
  25.756 +  {
  25.757 +    p1 = &self->mVertices[self->mIndices[i * 3 + 2] * 3];
  25.758 +    for(j = 0; j < 3; ++ j)
  25.759 +    {
  25.760 +      p2 = &self->mVertices[self->mIndices[i * 3 + j] * 3];
  25.761 +      avgEdgeLength += sqrtf((p2[0] - p1[0]) * (p2[0] - p1[0]) +
  25.762 +                             (p2[1] - p1[1]) * (p2[1] - p1[1]) +
  25.763 +                             (p2[2] - p1[2]) * (p2[2] - p1[2]));
  25.764 +      p1 = p2;
  25.765 +      ++ edgeCount;
  25.766 +    }
  25.767 +  }
  25.768 +  if(edgeCount == 0)
  25.769 +  {
  25.770 +    self->mError = CTM_INVALID_MESH;
  25.771 +    return;
  25.772 +  }
  25.773 +  avgEdgeLength /= (CTMfloat) edgeCount;
  25.774 +
  25.775 +  // Set precision
  25.776 +  self->mVertexPrecision = aRelPrecision * avgEdgeLength;
  25.777 +}
  25.778 +
  25.779 +//-----------------------------------------------------------------------------
  25.780 +// ctmNormalPrecision()
  25.781 +//-----------------------------------------------------------------------------
  25.782 +CTMEXPORT void CTMCALL ctmNormalPrecision(CTMcontext aContext,
  25.783 +  CTMfloat aPrecision)
  25.784 +{
  25.785 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.786 +  if(!self) return;
  25.787 +
  25.788 +  // You are only allowed to change compression attributes in export mode
  25.789 +  if(self->mMode != CTM_EXPORT)
  25.790 +  {
  25.791 +    self->mError = CTM_INVALID_OPERATION;
  25.792 +    return;
  25.793 +  }
  25.794 +
  25.795 +  // Check arguments
  25.796 +  if(aPrecision <= 0.0f)
  25.797 +  {
  25.798 +    self->mError = CTM_INVALID_ARGUMENT;
  25.799 +    return;
  25.800 +  }
  25.801 +
  25.802 +  // Set precision
  25.803 +  self->mNormalPrecision = aPrecision;
  25.804 +}
  25.805 +
  25.806 +//-----------------------------------------------------------------------------
  25.807 +// ctmUVCoordPrecision()
  25.808 +//-----------------------------------------------------------------------------
  25.809 +CTMEXPORT void CTMCALL ctmUVCoordPrecision(CTMcontext aContext,
  25.810 +  CTMenum aUVMap, CTMfloat aPrecision)
  25.811 +{
  25.812 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.813 +  _CTMfloatmap * map;
  25.814 +  CTMuint i;
  25.815 +  if(!self) return;
  25.816 +
  25.817 +  // You are only allowed to change compression attributes in export mode
  25.818 +  if(self->mMode != CTM_EXPORT)
  25.819 +  {
  25.820 +    self->mError = CTM_INVALID_OPERATION;
  25.821 +    return;
  25.822 +  }
  25.823 +
  25.824 +  // Check arguments
  25.825 +  if(aPrecision <= 0.0f)
  25.826 +  {
  25.827 +    self->mError = CTM_INVALID_ARGUMENT;
  25.828 +    return;
  25.829 +  }
  25.830 +
  25.831 +  // Find the indicated map
  25.832 +  map = self->mUVMaps;
  25.833 +  i = CTM_UV_MAP_1;
  25.834 +  while(map && (i != aUVMap))
  25.835 +  {
  25.836 +    ++ i;
  25.837 +    map = map->mNext;
  25.838 +  }
  25.839 +  if(!map)
  25.840 +  {
  25.841 +    self->mError = CTM_INVALID_ARGUMENT;
  25.842 +    return;
  25.843 +  }
  25.844 +
  25.845 +  // Update the precision
  25.846 +  map->mPrecision = aPrecision;
  25.847 +}
  25.848 +
  25.849 +//-----------------------------------------------------------------------------
  25.850 +// ctmAttribPrecision()
  25.851 +//-----------------------------------------------------------------------------
  25.852 +CTMEXPORT void CTMCALL ctmAttribPrecision(CTMcontext aContext,
  25.853 +  CTMenum aAttribMap, CTMfloat aPrecision)
  25.854 +{
  25.855 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.856 +  _CTMfloatmap * map;
  25.857 +  CTMuint i;
  25.858 +  if(!self) return;
  25.859 +
  25.860 +  // You are only allowed to change compression attributes in export mode
  25.861 +  if(self->mMode != CTM_EXPORT)
  25.862 +  {
  25.863 +    self->mError = CTM_INVALID_OPERATION;
  25.864 +    return;
  25.865 +  }
  25.866 +
  25.867 +  // Check arguments
  25.868 +  if(aPrecision <= 0.0f)
  25.869 +  {
  25.870 +    self->mError = CTM_INVALID_ARGUMENT;
  25.871 +    return;
  25.872 +  }
  25.873 +
  25.874 +  // Find the indicated map
  25.875 +  map = self->mAttribMaps;
  25.876 +  i = CTM_ATTRIB_MAP_1;
  25.877 +  while(map && (i != aAttribMap))
  25.878 +  {
  25.879 +    ++ i;
  25.880 +    map = map->mNext;
  25.881 +  }
  25.882 +  if(!map)
  25.883 +  {
  25.884 +    self->mError = CTM_INVALID_ARGUMENT;
  25.885 +    return;
  25.886 +  }
  25.887 +
  25.888 +  // Update the precision
  25.889 +  map->mPrecision = aPrecision;
  25.890 +}
  25.891 +
  25.892 +//-----------------------------------------------------------------------------
  25.893 +// ctmFileComment()
  25.894 +//-----------------------------------------------------------------------------
  25.895 +CTMEXPORT void CTMCALL ctmFileComment(CTMcontext aContext,
  25.896 +  const char * aFileComment)
  25.897 +{
  25.898 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.899 +  int len;
  25.900 +  if(!self) return;
  25.901 +
  25.902 +  // You are only allowed to change file attributes in export mode
  25.903 +  if(self->mMode != CTM_EXPORT)
  25.904 +  {
  25.905 +    self->mError = CTM_INVALID_OPERATION;
  25.906 +    return;
  25.907 +  }
  25.908 +
  25.909 +  // Free the old comment string, if necessary
  25.910 +  if(self->mFileComment)
  25.911 +  {
  25.912 +    free(self->mFileComment);
  25.913 +    self->mFileComment = (char *) 0;
  25.914 +  }
  25.915 +
  25.916 +  // Get length of string (if empty, do nothing)
  25.917 +  if(!aFileComment)
  25.918 +    return;
  25.919 +  len = strlen(aFileComment);
  25.920 +  if(!len)
  25.921 +    return;
  25.922 +
  25.923 +  // Copy the string
  25.924 +  self->mFileComment = (char *) malloc(len + 1);
  25.925 +  if(!self->mFileComment)
  25.926 +  {
  25.927 +    self->mError = CTM_OUT_OF_MEMORY;
  25.928 +    return;
  25.929 +  }
  25.930 +  strcpy(self->mFileComment, aFileComment);
  25.931 +}
  25.932 +
  25.933 +//-----------------------------------------------------------------------------
  25.934 +// ctmDefineMesh()
  25.935 +//-----------------------------------------------------------------------------
  25.936 +CTMEXPORT void CTMCALL ctmDefineMesh(CTMcontext aContext,
  25.937 +  const CTMfloat * aVertices, CTMuint aVertexCount, const CTMuint * aIndices,
  25.938 +  CTMuint aTriangleCount, const CTMfloat * aNormals)
  25.939 +{
  25.940 +  _CTMcontext * self = (_CTMcontext *) aContext;
  25.941 +  if(!self) return;
  25.942 +
  25.943 +  // You are only allowed to (re)define the mesh in export mode
  25.944 +  if(self->mMode != CTM_EXPORT)
  25.945 +  {
  25.946 +    self->mError = CTM_INVALID_OPERATION;
  25.947 +    return;
  25.948 +  }
  25.949 +
  25.950 +  // Check arguments
  25.951 +  if(!aVertices || !aIndices || !aVertexCount || !aTriangleCount)
  25.952 +  {
  25.953 +    self->mError = CTM_INVALID_ARGUMENT;
  25.954 +    return;
  25.955 +  }
  25.956 +
  25.957 +  // Clear the old mesh, if any
  25.958 +  _ctmClearMesh(self);
  25.959 +
  25.960 +  // Set vertex array pointer
  25.961 +  self->mVertices = (CTMfloat *) aVertices;
  25.962 +  self->mVertexCount = aVertexCount;
  25.963 +
  25.964 +  // Set index array pointer
  25.965 +  self->mIndices = (CTMuint *) aIndices;
  25.966 +  self->mTriangleCount = aTriangleCount;
  25.967 +
  25.968 +  // Set normal array pointer
  25.969 +  self->mNormals = (CTMfloat *) aNormals;
  25.970 +}
  25.971 +
  25.972 +//-----------------------------------------------------------------------------
  25.973 +// _ctmAddFloatMap()
  25.974 +//-----------------------------------------------------------------------------
  25.975 +static _CTMfloatmap * _ctmAddFloatMap(_CTMcontext * self,
  25.976 +  const CTMfloat * aValues, const char * aName, const char * aFileName,
  25.977 +  _CTMfloatmap ** aList)
  25.978 +{
  25.979 +  _CTMfloatmap * map;
  25.980 +  CTMuint len;
  25.981 +
  25.982 +  // Allocate memory for a new map list item and append it to the list
  25.983 +  if(!*aList)
  25.984 +  {
  25.985 +    *aList = (_CTMfloatmap *) malloc(sizeof(_CTMfloatmap));
  25.986 +    map = *aList;
  25.987 +  }
  25.988 +  else
  25.989 +  {
  25.990 +    map = *aList;
  25.991 +    while(map->mNext)
  25.992 +      map = map->mNext;
  25.993 +    map->mNext = (_CTMfloatmap *) malloc(sizeof(_CTMfloatmap));
  25.994 +    map = map->mNext;
  25.995 +  }
  25.996 +  if(!map)
  25.997 +  {
  25.998 +    self->mError = CTM_OUT_OF_MEMORY;
  25.999 +    return (_CTMfloatmap *) 0;
 25.1000 +  }
 25.1001 +
 25.1002 +  // Init the map item
 25.1003 +  memset(map, 0, sizeof(_CTMfloatmap));
 25.1004 +  map->mPrecision = 1.0f / 1024.0f;
 25.1005 +  map->mValues = (CTMfloat *) aValues;
 25.1006 +
 25.1007 +  // Set name of the map
 25.1008 +  if(aName)
 25.1009 +  {
 25.1010 +    // Get length of string (if empty, do nothing)
 25.1011 +    len = strlen(aName);
 25.1012 +    if(len)
 25.1013 +    {
 25.1014 +      // Copy the string
 25.1015 +      map->mName = (char *) malloc(len + 1);
 25.1016 +      if(!map->mName)
 25.1017 +      {
 25.1018 +        self->mError = CTM_OUT_OF_MEMORY;
 25.1019 +        free(map);
 25.1020 +        return (_CTMfloatmap *) 0;
 25.1021 +      }
 25.1022 +      strcpy(map->mName, aName);
 25.1023 +    }
 25.1024 +  }
 25.1025 +
 25.1026 +  // Set file name reference for the map
 25.1027 +  if(aFileName)
 25.1028 +  {
 25.1029 +    // Get length of string (if empty, do nothing)
 25.1030 +    len = strlen(aFileName);
 25.1031 +    if(len)
 25.1032 +    {
 25.1033 +      // Copy the string
 25.1034 +      map->mFileName = (char *) malloc(len + 1);
 25.1035 +      if(!map->mFileName)
 25.1036 +      {
 25.1037 +        self->mError = CTM_OUT_OF_MEMORY;
 25.1038 +        if(map->mName)
 25.1039 +          free(map->mName);
 25.1040 +        free(map);
 25.1041 +        return (_CTMfloatmap *) 0;
 25.1042 +      }
 25.1043 +      strcpy(map->mFileName, aFileName);
 25.1044 +    }
 25.1045 +  }
 25.1046 +
 25.1047 +  return map;
 25.1048 +}
 25.1049 +
 25.1050 +//-----------------------------------------------------------------------------
 25.1051 +// ctmAddUVMap()
 25.1052 +//-----------------------------------------------------------------------------
 25.1053 +CTMEXPORT CTMenum CTMCALL ctmAddUVMap(CTMcontext aContext,
 25.1054 +  const CTMfloat * aUVCoords, const char * aName, const char * aFileName)
 25.1055 +{
 25.1056 +  _CTMcontext * self = (_CTMcontext *) aContext;
 25.1057 +  _CTMfloatmap * map;
 25.1058 +  if(!self) return CTM_NONE;
 25.1059 +
 25.1060 +  // Add a new UV map to the UV map list
 25.1061 +  map = _ctmAddFloatMap(self, aUVCoords, aName, aFileName, &self->mUVMaps);
 25.1062 +  if(!map)
 25.1063 +    return CTM_NONE;
 25.1064 +  else
 25.1065 +  {
 25.1066 +    // The default UV coordinate precision is 2^-12
 25.1067 +    map->mPrecision = 1.0f / 4096.0f;
 25.1068 +    ++ self->mUVMapCount;
 25.1069 +    return CTM_UV_MAP_1 + self->mUVMapCount - 1;
 25.1070 +  }
 25.1071 +}
 25.1072 +
 25.1073 +//-----------------------------------------------------------------------------
 25.1074 +// ctmAddAttribMap()
 25.1075 +//-----------------------------------------------------------------------------
 25.1076 +CTMEXPORT CTMenum CTMCALL ctmAddAttribMap(CTMcontext aContext,
 25.1077 +  const CTMfloat * aAttribValues, const char * aName)
 25.1078 +{
 25.1079 +  _CTMcontext * self = (_CTMcontext *) aContext;
 25.1080 +  _CTMfloatmap * map;
 25.1081 +  if(!self) return CTM_NONE;
 25.1082 +
 25.1083 +  // Add a new attribute map to the attribute map list
 25.1084 +  map = _ctmAddFloatMap(self, aAttribValues, aName, (const char *) 0,
 25.1085 +                        &self->mAttribMaps);
 25.1086 +  if(!map)
 25.1087 +    return CTM_NONE;
 25.1088 +  else
 25.1089 +  {
 25.1090 +    // The default vertex attribute precision is 2^-8
 25.1091 +    map->mPrecision = 1.0f / 256.0f;
 25.1092 +    ++ self->mAttribMapCount;
 25.1093 +    return CTM_ATTRIB_MAP_1 + self->mAttribMapCount - 1;
 25.1094 +  }
 25.1095 +}
 25.1096 +
 25.1097 +//-----------------------------------------------------------------------------
 25.1098 +// _ctmDefaultRead()
 25.1099 +//-----------------------------------------------------------------------------
 25.1100 +static CTMuint CTMCALL _ctmDefaultRead(void * aBuf, CTMuint aCount,
 25.1101 +  void * aUserData)
 25.1102 +{
 25.1103 +  return (CTMuint) fread(aBuf, 1, (size_t) aCount, (FILE *) aUserData);
 25.1104 +}
 25.1105 +
 25.1106 +//-----------------------------------------------------------------------------
 25.1107 +// ctmLoad()
 25.1108 +//-----------------------------------------------------------------------------
 25.1109 +CTMEXPORT void CTMCALL ctmLoad(CTMcontext aContext, const char * aFileName)
 25.1110 +{
 25.1111 +  _CTMcontext * self = (_CTMcontext *) aContext;
 25.1112 +  FILE * f;
 25.1113 +  if(!self) return;
 25.1114 +
 25.1115 +  // You are only allowed to load data in import mode
 25.1116 +  if(self->mMode != CTM_IMPORT)
 25.1117 +  {
 25.1118 +    self->mError = CTM_INVALID_OPERATION;
 25.1119 +    return;
 25.1120 +  }
 25.1121 +
 25.1122 +  // Open file stream
 25.1123 +  f = fopen(aFileName, "rb");
 25.1124 +  if(!f)
 25.1125 +  {
 25.1126 +    self->mError = CTM_FILE_ERROR;
 25.1127 +    return;
 25.1128 +  }
 25.1129 +
 25.1130 +  // Load the file
 25.1131 +  ctmLoadCustom(self, _ctmDefaultRead, (void *) f);
 25.1132 +
 25.1133 +  // Close file stream
 25.1134 +  fclose(f);
 25.1135 +}
 25.1136 +
 25.1137 +//-----------------------------------------------------------------------------
 25.1138 +// _ctmAllocateFloatMaps()
 25.1139 +//-----------------------------------------------------------------------------
 25.1140 +static CTMuint _ctmAllocateFloatMaps(_CTMcontext * self,
 25.1141 +  _CTMfloatmap ** aMapListPtr, CTMuint aCount, CTMuint aChannels)
 25.1142 +{
 25.1143 +  _CTMfloatmap ** mapListPtr;
 25.1144 +  CTMuint i, size;
 25.1145 +
 25.1146 +  mapListPtr = aMapListPtr;
 25.1147 +  for(i = 0; i < aCount; ++ i)
 25.1148 +  {
 25.1149 +    // Allocate & clear memory for this map
 25.1150 +    *mapListPtr = (_CTMfloatmap *) malloc(sizeof(_CTMfloatmap));
 25.1151 +    if(!*mapListPtr)
 25.1152 +    {
 25.1153 +      self->mError = CTM_OUT_OF_MEMORY;
 25.1154 +      return CTM_FALSE;
 25.1155 +    }
 25.1156 +    memset(*mapListPtr, 0, sizeof(_CTMfloatmap));
 25.1157 +
 25.1158 +    // Allocate & clear memory for the float array
 25.1159 +    size = aChannels * sizeof(CTMfloat) * self->mVertexCount;
 25.1160 +    (*mapListPtr)->mValues = (CTMfloat *) malloc(size);
 25.1161 +    if(!(*mapListPtr)->mValues)
 25.1162 +    {
 25.1163 +      self->mError = CTM_OUT_OF_MEMORY;
 25.1164 +      return CTM_FALSE;
 25.1165 +    }
 25.1166 +    memset((*mapListPtr)->mValues, 0, size);
 25.1167 +
 25.1168 +    // Next map...
 25.1169 +    mapListPtr = &(*mapListPtr)->mNext;
 25.1170 +  }
 25.1171 +
 25.1172 +  return CTM_TRUE;
 25.1173 +}
 25.1174 +
 25.1175 +//-----------------------------------------------------------------------------
 25.1176 +// ctmLoadCustom()
 25.1177 +//-----------------------------------------------------------------------------
 25.1178 +CTMEXPORT void CTMCALL ctmLoadCustom(CTMcontext aContext, CTMreadfn aReadFn,
 25.1179 +  void * aUserData)
 25.1180 +{
 25.1181 +  _CTMcontext * self = (_CTMcontext *) aContext;
 25.1182 +  CTMuint formatVersion, flags, method;
 25.1183 +  if(!self) return;
 25.1184 +
 25.1185 +  // You are only allowed to load data in import mode
 25.1186 +  if(self->mMode != CTM_IMPORT)
 25.1187 +  {
 25.1188 +    self->mError = CTM_INVALID_OPERATION;
 25.1189 +    return;
 25.1190 +  }
 25.1191 +
 25.1192 +  // Initialize stream
 25.1193 +  self->mReadFn = aReadFn;
 25.1194 +  self->mUserData = aUserData;
 25.1195 +
 25.1196 +  // Clear any old mesh arrays
 25.1197 +  _ctmClearMesh(self);
 25.1198 +
 25.1199 +  // Read header from stream
 25.1200 +  if(_ctmStreamReadUINT(self) != FOURCC("OCTM"))
 25.1201 +  {
 25.1202 +    self->mError = CTM_BAD_FORMAT;
 25.1203 +    return;
 25.1204 +  }
 25.1205 +  formatVersion = _ctmStreamReadUINT(self);
 25.1206 +  if(formatVersion != _CTM_FORMAT_VERSION)
 25.1207 +  {
 25.1208 +    self->mError = CTM_UNSUPPORTED_FORMAT_VERSION;
 25.1209 +    return;
 25.1210 +  }
 25.1211 +  method = _ctmStreamReadUINT(self);
 25.1212 +  if(method == FOURCC("RAW\0"))
 25.1213 +    self->mMethod = CTM_METHOD_RAW;
 25.1214 +  else if(method == FOURCC("MG1\0"))
 25.1215 +    self->mMethod = CTM_METHOD_MG1;
 25.1216 +  else if(method == FOURCC("MG2\0"))
 25.1217 +    self->mMethod = CTM_METHOD_MG2;
 25.1218 +  else
 25.1219 +  {
 25.1220 +    self->mError = CTM_BAD_FORMAT;
 25.1221 +    return;
 25.1222 +  }
 25.1223 +  self->mVertexCount = _ctmStreamReadUINT(self);
 25.1224 +  if(self->mVertexCount == 0)
 25.1225 +  {
 25.1226 +    self->mError = CTM_BAD_FORMAT;
 25.1227 +    return;
 25.1228 +  }
 25.1229 +  self->mTriangleCount = _ctmStreamReadUINT(self);
 25.1230 +  if(self->mTriangleCount == 0)
 25.1231 +  {
 25.1232 +    self->mError = CTM_BAD_FORMAT;
 25.1233 +    return;
 25.1234 +  }
 25.1235 +  self->mUVMapCount = _ctmStreamReadUINT(self);
 25.1236 +  self->mAttribMapCount = _ctmStreamReadUINT(self);
 25.1237 +  flags = _ctmStreamReadUINT(self);
 25.1238 +  _ctmStreamReadSTRING(self, &self->mFileComment);
 25.1239 +
 25.1240 +  // Allocate memory for the mesh arrays
 25.1241 +  self->mVertices = (CTMfloat *) malloc(self->mVertexCount * sizeof(CTMfloat) * 3);
 25.1242 +  if(!self->mVertices)
 25.1243 +  {
 25.1244 +    self->mError = CTM_OUT_OF_MEMORY;
 25.1245 +    return;
 25.1246 +  }
 25.1247 +  self->mIndices = (CTMuint *) malloc(self->mTriangleCount * sizeof(CTMuint) * 3);
 25.1248 +  if(!self->mIndices)
 25.1249 +  {
 25.1250 +    _ctmClearMesh(self);
 25.1251 +    self->mError = CTM_OUT_OF_MEMORY;
 25.1252 +    return;
 25.1253 +  }
 25.1254 +  if(flags & _CTM_HAS_NORMALS_BIT)
 25.1255 +  {
 25.1256 +    self->mNormals = (CTMfloat *) malloc(self->mVertexCount * sizeof(CTMfloat) * 3);
 25.1257 +    if(!self->mNormals)
 25.1258 +    {
 25.1259 +      _ctmClearMesh(self);
 25.1260 +      self->mError = CTM_OUT_OF_MEMORY;
 25.1261 +      return;
 25.1262 +    }
 25.1263 +  }
 25.1264 +
 25.1265 +  // Allocate memory for the UV and attribute maps (if any)
 25.1266 +  if(!_ctmAllocateFloatMaps(self, &self->mUVMaps, self->mUVMapCount, 2))
 25.1267 +  {
 25.1268 +    _ctmClearMesh(self);
 25.1269 +    self->mError = CTM_OUT_OF_MEMORY;
 25.1270 +    return;
 25.1271 +  }
 25.1272 +  if(!_ctmAllocateFloatMaps(self, &self->mAttribMaps, self->mAttribMapCount, 4))
 25.1273 +  {
 25.1274 +    _ctmClearMesh(self);
 25.1275 +    self->mError = CTM_OUT_OF_MEMORY;
 25.1276 +    return;
 25.1277 +  }
 25.1278 +
 25.1279 +  // Uncompress from stream
 25.1280 +  switch(self->mMethod)
 25.1281 +  {
 25.1282 +    case CTM_METHOD_RAW:
 25.1283 +      _ctmUncompressMesh_RAW(self);
 25.1284 +      break;
 25.1285 +
 25.1286 +    case CTM_METHOD_MG1:
 25.1287 +      _ctmUncompressMesh_MG1(self);
 25.1288 +      break;
 25.1289 +
 25.1290 +    case CTM_METHOD_MG2:
 25.1291 +      _ctmUncompressMesh_MG2(self);
 25.1292 +      break;
 25.1293 +
 25.1294 +    default:
 25.1295 +      self->mError = CTM_INTERNAL_ERROR;
 25.1296 +  }
 25.1297 +
 25.1298 +  // Check mesh integrity
 25.1299 +  if(!_ctmCheckMeshIntegrity(self))
 25.1300 +  {
 25.1301 +    self->mError = CTM_INVALID_MESH;
 25.1302 +    return;
 25.1303 +  }
 25.1304 +}
 25.1305 +
 25.1306 +//-----------------------------------------------------------------------------
 25.1307 +// _ctmDefaultWrite()
 25.1308 +//-----------------------------------------------------------------------------
 25.1309 +static CTMuint CTMCALL _ctmDefaultWrite(const void * aBuf, CTMuint aCount,
 25.1310 +  void * aUserData)
 25.1311 +{
 25.1312 +  return (CTMuint) fwrite(aBuf, 1, (size_t) aCount, (FILE *) aUserData);
 25.1313 +}
 25.1314 +
 25.1315 +//-----------------------------------------------------------------------------
 25.1316 +// ctmSave()
 25.1317 +//-----------------------------------------------------------------------------
 25.1318 +CTMEXPORT void CTMCALL ctmSave(CTMcontext aContext, const char * aFileName)
 25.1319 +{
 25.1320 +  _CTMcontext * self = (_CTMcontext *) aContext;
 25.1321 +  FILE * f;
 25.1322 +  if(!self) return;
 25.1323 +
 25.1324 +  // You are only allowed to save data in export mode
 25.1325 +  if(self->mMode != CTM_EXPORT)
 25.1326 +  {
 25.1327 +    self->mError = CTM_INVALID_OPERATION;
 25.1328 +    return;
 25.1329 +  }
 25.1330 +
 25.1331 +  // Open file stream
 25.1332 +  f = fopen(aFileName, "wb");
 25.1333 +  if(!f)
 25.1334 +  {
 25.1335 +    self->mError = CTM_FILE_ERROR;
 25.1336 +    return;
 25.1337 +  }
 25.1338 +
 25.1339 +  // Save the file
 25.1340 +  ctmSaveCustom(self, _ctmDefaultWrite, (void *) f);
 25.1341 +
 25.1342 +  // Close file stream
 25.1343 +  fclose(f);
 25.1344 +}
 25.1345 +
 25.1346 +//-----------------------------------------------------------------------------
 25.1347 +// ctmSaveCustom()
 25.1348 +//-----------------------------------------------------------------------------
 25.1349 +void CTMCALL ctmSaveCustom(CTMcontext aContext, CTMwritefn aWriteFn,
 25.1350 +  void * aUserData)
 25.1351 +{
 25.1352 +  _CTMcontext * self = (_CTMcontext *) aContext;
 25.1353 +  CTMuint flags;
 25.1354 +  if(!self) return;
 25.1355 +
 25.1356 +  // You are only allowed to save data in export mode
 25.1357 +  if(self->mMode != CTM_EXPORT)
 25.1358 +  {
 25.1359 +    self->mError = CTM_INVALID_OPERATION;
 25.1360 +    return;
 25.1361 +  }
 25.1362 +
 25.1363 +  // Check mesh integrity
 25.1364 +  if(!_ctmCheckMeshIntegrity(self))
 25.1365 +  {
 25.1366 +    self->mError = CTM_INVALID_MESH;
 25.1367 +    return;
 25.1368 +  }
 25.1369 +
 25.1370 +  // Initialize stream
 25.1371 +  self->mWriteFn = aWriteFn;
 25.1372 +  self->mUserData = aUserData;
 25.1373 +
 25.1374 +  // Determine flags
 25.1375 +  flags = 0;
 25.1376 +  if(self->mNormals)
 25.1377 +    flags |= _CTM_HAS_NORMALS_BIT;
 25.1378 +
 25.1379 +  // Write header to stream
 25.1380 +  _ctmStreamWrite(self, (void *) "OCTM", 4);
 25.1381 +  _ctmStreamWriteUINT(self, _CTM_FORMAT_VERSION);
 25.1382 +  switch(self->mMethod)
 25.1383 +  {
 25.1384 +    case CTM_METHOD_RAW:
 25.1385 +      _ctmStreamWrite(self, (void *) "RAW\0", 4);
 25.1386 +      break;
 25.1387 +
 25.1388 +    case CTM_METHOD_MG1:
 25.1389 +      _ctmStreamWrite(self, (void *) "MG1\0", 4);
 25.1390 +      break;
 25.1391 +
 25.1392 +    case CTM_METHOD_MG2:
 25.1393 +      _ctmStreamWrite(self, (void *) "MG2\0", 4);
 25.1394 +      break;
 25.1395 +
 25.1396 +    default:
 25.1397 +      self->mError = CTM_INTERNAL_ERROR;
 25.1398 +      return;
 25.1399 +  }
 25.1400 +  _ctmStreamWriteUINT(self, self->mVertexCount);
 25.1401 +  _ctmStreamWriteUINT(self, self->mTriangleCount);
 25.1402 +  _ctmStreamWriteUINT(self, self->mUVMapCount);
 25.1403 +  _ctmStreamWriteUINT(self, self->mAttribMapCount);
 25.1404 +  _ctmStreamWriteUINT(self, flags);
 25.1405 +  _ctmStreamWriteSTRING(self, self->mFileComment);
 25.1406 +
 25.1407 +  // Compress to stream
 25.1408 +  switch(self->mMethod)
 25.1409 +  {
 25.1410 +    case CTM_METHOD_RAW:
 25.1411 +      _ctmCompressMesh_RAW(self);
 25.1412 +      break;
 25.1413 +
 25.1414 +    case CTM_METHOD_MG1:
 25.1415 +      _ctmCompressMesh_MG1(self);
 25.1416 +      break;
 25.1417 +
 25.1418 +    case CTM_METHOD_MG2:
 25.1419 +      _ctmCompressMesh_MG2(self);
 25.1420 +      break;
 25.1421 +
 25.1422 +    default:
 25.1423 +      self->mError = CTM_INTERNAL_ERROR;
 25.1424 +      return;
 25.1425 +  }
 25.1426 +}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/libs/openctm/openctm.h	Thu Sep 26 04:47:05 2013 +0300
    26.3 @@ -0,0 +1,655 @@
    26.4 +//-----------------------------------------------------------------------------
    26.5 +// Product:     OpenCTM
    26.6 +// File:        openctm.h
    26.7 +// Description: OpenCTM API definition.
    26.8 +//-----------------------------------------------------------------------------
    26.9 +// Copyright (c) 2009-2010 Marcus Geelnard
   26.10 +//
   26.11 +// This software is provided 'as-is', without any express or implied
   26.12 +// warranty. In no event will the authors be held liable for any damages
   26.13 +// arising from the use of this software.
   26.14 +//
   26.15 +// Permission is granted to anyone to use this software for any purpose,
   26.16 +// including commercial applications, and to alter it and redistribute it
   26.17 +// freely, subject to the following restrictions:
   26.18 +//
   26.19 +//     1. The origin of this software must not be misrepresented; you must not
   26.20 +//     claim that you wrote the original software. If you use this software
   26.21 +//     in a product, an acknowledgment in the product documentation would be
   26.22 +//     appreciated but is not required.
   26.23 +//
   26.24 +//     2. Altered source versions must be plainly marked as such, and must not
   26.25 +//     be misrepresented as being the original software.
   26.26 +//
   26.27 +//     3. This notice may not be removed or altered from any source
   26.28 +//     distribution.
   26.29 +//-----------------------------------------------------------------------------
   26.30 +
   26.31 +#ifndef __OPENCTM_H_
   26.32 +#define __OPENCTM_H_
   26.33 +
   26.34 +/*! @mainpage OpenCTM API Reference
   26.35 + *
   26.36 + * @section intro_sec Introduction
   26.37 + *
   26.38 + * OpenCTM is an open file format for storing compressed triangle meshes.
   26.39 + * In order to easily read and write OpenCTM files (usually suffixed .ctm) an
   26.40 + * API (Application Program Interface) is provided that can easily be used from
   26.41 + * most modern programming languages.
   26.42 + *
   26.43 + * The OpenCTM functionality itself is written in highly portable standard C
   26.44 + * (C99).
   26.45 + *
   26.46 + * @section usage_sec Usage
   26.47 + *
   26.48 + * For information about how to use the OpenCTM API, see openctm.h.
   26.49 + *
   26.50 + * For information about the C++ wrapper classes, see CTMimporter and
   26.51 + * CTMexporter.
   26.52 + *
   26.53 + * @section example_sec Example usage
   26.54 + *
   26.55 + * @subsection example_load_sec Loading a CTM file
   26.56 + *
   26.57 + * Here is a simple example of loading a CTM file:
   26.58 + *
   26.59 + * @code
   26.60 + *   CTMcontext context;
   26.61 + *   CTMuint    vertCount, triCount, * indices;
   26.62 + *   CTMfloat   * vertices;
   26.63 + *
   26.64 + *   // Create a new context
   26.65 + *   context = ctmNewContext(CTM_IMPORT);
   26.66 + *
   26.67 + *   // Load the OpenCTM file
   26.68 + *   ctmLoad(context, "mymesh.ctm");
   26.69 + *   if(ctmGetError(context) == CTM_NONE)
   26.70 + *   {
   26.71 + *     // Access the mesh data
   26.72 + *     vertCount = ctmGetInteger(context, CTM_VERTEX_COUNT);
   26.73 + *     vertices = ctmGetFloatArray(context, CTM_VERTICES);
   26.74 + *     triCount = ctmGetInteger(context, CTM_TRIANGLE_COUNT);
   26.75 + *     indices = ctmGetIntegerArray(context, CTM_INDICES);
   26.76 + *
   26.77 + *     // Deal with the mesh (e.g. transcode it to our internal representation)
   26.78 + *     // ...
   26.79 + *   }
   26.80 + *
   26.81 + *   // Free the context
   26.82 + *   ctmFreeContext(context);
   26.83 + * @endcode
   26.84 + *
   26.85 + * @subsection example_create_sec Creating a CTM file
   26.86 + *
   26.87 + * Here is a simple example of creating a CTM file:
   26.88 + *
   26.89 + * @code
   26.90 + *   CTMcontext context;
   26.91 + *   CTMuint    vertCount, triCount, * indices;
   26.92 + *   CTMfloat   * vertices;
   26.93 + *
   26.94 + *   // Create our mesh in memory
   26.95 + *   vertCount = 100;
   26.96 + *   triCount = 120;
   26.97 + *   vertices = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * vertCount);
   26.98 + *   indices = (CTMuint *) malloc(3 * sizeof(CTMuint) * triCount);
   26.99 + *   // ...
  26.100 + *
  26.101 + *   // Create a new context
  26.102 + *   context = ctmNewContext(CTM_EXPORT);
  26.103 + *
  26.104 + *   // Define our mesh representation to OpenCTM (store references to it in
  26.105 + *   // the context)
  26.106 + *   ctmDefineMesh(context, vertices, vertCount, indices, triCount, NULL);
  26.107 + *
  26.108 + *   // Save the OpenCTM file
  26.109 + *   ctmSave(context, "mymesh.ctm");
  26.110 + *
  26.111 + *   // Free the context
  26.112 + *   ctmFreeContext(context);
  26.113 + *
  26.114 + *   // Free our mesh
  26.115 + *   free(indices);
  26.116 + *   free(vertices);
  26.117 + * @endcode
  26.118 + */
  26.119 +
  26.120 +#ifdef __cplusplus
  26.121 +extern "C" {
  26.122 +#endif
  26.123 +
  26.124 +
  26.125 +// Declare calling conventions etc.
  26.126 +#if defined(WIN32) || defined(_WIN32)
  26.127 +  // Windows
  26.128 +  #if defined(OPENCTM_STATIC)
  26.129 +    #define CTMEXPORT
  26.130 +  #else
  26.131 +    #if defined(OPENCTM_BUILD)
  26.132 +      #define CTMEXPORT __declspec(dllexport)
  26.133 +    #else
  26.134 +      #define CTMEXPORT __declspec(dllimport)
  26.135 +    #endif
  26.136 +  #endif
  26.137 +  #if defined(__MINGW32__)
  26.138 +    #define CTMCALL __attribute__ ((__stdcall__))
  26.139 +  #elif (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)
  26.140 +    #define CTMCALL __stdcall
  26.141 +  #else
  26.142 +    #define CTMCALL
  26.143 +  #endif
  26.144 +#else
  26.145 +  // Unix
  26.146 +  #if !defined(OPENCTM_STATIC) && !defined(OPENCTM_BUILD)
  26.147 +    #define CTMEXPORT extern
  26.148 +  #else
  26.149 +    #if defined(OPENCTM_BUILD) && defined(__GNUC__) && (__GNUC__ >= 4)
  26.150 +      #define CTMEXPORT __attribute__ ((visibility("default")))
  26.151 +    #else
  26.152 +      #define CTMEXPORT
  26.153 +    #endif
  26.154 +  #endif
  26.155 +  #define CTMCALL
  26.156 +#endif
  26.157 +
  26.158 +
  26.159 +// Get system specific type definitions for sized integers. We use the C99
  26.160 +// standard stdint.h for this.
  26.161 +#ifdef _MSC_VER
  26.162 +  // MS Visual Studio does not support C99
  26.163 +  typedef int int32_t;
  26.164 +  typedef unsigned int uint32_t;
  26.165 +#else
  26.166 +  #include <stdint.h>
  26.167 +#endif
  26.168 +
  26.169 +
  26.170 +/// OpenCTM API version (1.0).
  26.171 +#define CTM_API_VERSION 0x00000100
  26.172 +
  26.173 +/// Boolean TRUE.
  26.174 +#define CTM_TRUE 1
  26.175 +
  26.176 +/// Boolean FALSE.
  26.177 +#define CTM_FALSE 0
  26.178 +
  26.179 +/// Single precision floating point type (IEEE 754 32 bits wide).
  26.180 +typedef float CTMfloat;
  26.181 +
  26.182 +/// Signed integer (32 bits wide).
  26.183 +typedef int32_t CTMint;
  26.184 +
  26.185 +/// Unsigned integer (32 bits wide).
  26.186 +typedef uint32_t CTMuint;
  26.187 +
  26.188 +/// OpenCTM context handle.
  26.189 +typedef void * CTMcontext;
  26.190 +
  26.191 +/// OpenCTM specific enumerators.
  26.192 +/// @note For the information query functions, it is an error to query a value
  26.193 +///       of the wrong type (e.g. to query a string value with the
  26.194 +///       ctmGetInteger() function).
  26.195 +typedef enum {
  26.196 +  // Error codes (see ctmGetError())
  26.197 +  CTM_NONE              = 0x0000, ///< No error has occured (everything is OK).
  26.198 +                                  ///  Also used as an error return value for
  26.199 +                                  ///  functions that should return a CTMenum
  26.200 +                                  ///  value.
  26.201 +  CTM_INVALID_CONTEXT   = 0x0001, ///< The OpenCTM context was invalid (e.g. NULL).
  26.202 +  CTM_INVALID_ARGUMENT  = 0x0002, ///< A function argument was invalid.
  26.203 +  CTM_INVALID_OPERATION = 0x0003, ///< The operation is not allowed.
  26.204 +  CTM_INVALID_MESH      = 0x0004, ///< The mesh was invalid (e.g. no vertices).
  26.205 +  CTM_OUT_OF_MEMORY     = 0x0005, ///< Not enough memory to proceed.
  26.206 +  CTM_FILE_ERROR        = 0x0006, ///< File I/O error.
  26.207 +  CTM_BAD_FORMAT        = 0x0007, ///< File format error (e.g. unrecognized format or corrupted file).
  26.208 +  CTM_LZMA_ERROR        = 0x0008, ///< An error occured within the LZMA library.
  26.209 +  CTM_INTERNAL_ERROR    = 0x0009, ///< An internal error occured (indicates a bug).
  26.210 +  CTM_UNSUPPORTED_FORMAT_VERSION = 0x000A, ///< Unsupported file format version.
  26.211 +
  26.212 +  // OpenCTM context modes
  26.213 +  CTM_IMPORT            = 0x0101, ///< The OpenCTM context will be used for importing data.
  26.214 +  CTM_EXPORT            = 0x0102, ///< The OpenCTM context will be used for exporting data.
  26.215 +
  26.216 +  // Compression methods
  26.217 +  CTM_METHOD_RAW        = 0x0201, ///< Just store the raw data.
  26.218 +  CTM_METHOD_MG1        = 0x0202, ///< Lossless compression (floating point).
  26.219 +  CTM_METHOD_MG2        = 0x0203, ///< Lossless compression (fixed point).
  26.220 +
  26.221 +  // Context queries
  26.222 +  CTM_VERTEX_COUNT      = 0x0301, ///< Number of vertices in the mesh (integer).
  26.223 +  CTM_TRIANGLE_COUNT    = 0x0302, ///< Number of triangles in the mesh (integer).
  26.224 +  CTM_HAS_NORMALS       = 0x0303, ///< CTM_TRUE if the mesh has normals (integer).
  26.225 +  CTM_UV_MAP_COUNT      = 0x0304, ///< Number of UV coordinate sets (integer).
  26.226 +  CTM_ATTRIB_MAP_COUNT  = 0x0305, ///< Number of custom attribute sets (integer).
  26.227 +  CTM_VERTEX_PRECISION  = 0x0306, ///< Vertex precision - for MG2 (float).
  26.228 +  CTM_NORMAL_PRECISION  = 0x0307, ///< Normal precision - for MG2 (float).
  26.229 +  CTM_COMPRESSION_METHOD = 0x0308, ///< Compression method (integer).
  26.230 +  CTM_FILE_COMMENT      = 0x0309, ///< File comment (string).
  26.231 +
  26.232 +  // UV/attribute map queries
  26.233 +  CTM_NAME              = 0x0501, ///< Unique name (UV/attrib map string).
  26.234 +  CTM_FILE_NAME         = 0x0502, ///< File name reference (UV map string).
  26.235 +  CTM_PRECISION         = 0x0503, ///< Value precision (UV/attrib map float).
  26.236 +
  26.237 +  // Array queries
  26.238 +  CTM_INDICES           = 0x0601, ///< Triangle indices (integer array).
  26.239 +  CTM_VERTICES          = 0x0602, ///< Vertex point coordinates (float array).
  26.240 +  CTM_NORMALS           = 0x0603, ///< Per vertex normals (float array).
  26.241 +  CTM_UV_MAP_1          = 0x0700, ///< Per vertex UV map 1 (float array).
  26.242 +  CTM_UV_MAP_2          = 0x0701, ///< Per vertex UV map 2 (float array).
  26.243 +  CTM_UV_MAP_3          = 0x0702, ///< Per vertex UV map 3 (float array).
  26.244 +  CTM_UV_MAP_4          = 0x0703, ///< Per vertex UV map 4 (float array).
  26.245 +  CTM_UV_MAP_5          = 0x0704, ///< Per vertex UV map 5 (float array).
  26.246 +  CTM_UV_MAP_6          = 0x0705, ///< Per vertex UV map 6 (float array).
  26.247 +  CTM_UV_MAP_7          = 0x0706, ///< Per vertex UV map 7 (float array).
  26.248 +  CTM_UV_MAP_8          = 0x0707, ///< Per vertex UV map 8 (float array).
  26.249 +  CTM_ATTRIB_MAP_1      = 0x0800, ///< Per vertex attribute map 1 (float array).
  26.250 +  CTM_ATTRIB_MAP_2      = 0x0801, ///< Per vertex attribute map 2 (float array).
  26.251 +  CTM_ATTRIB_MAP_3      = 0x0802, ///< Per vertex attribute map 3 (float array).
  26.252 +  CTM_ATTRIB_MAP_4      = 0x0803, ///< Per vertex attribute map 4 (float array).
  26.253 +  CTM_ATTRIB_MAP_5      = 0x0804, ///< Per vertex attribute map 5 (float array).
  26.254 +  CTM_ATTRIB_MAP_6      = 0x0805, ///< Per vertex attribute map 6 (float array).
  26.255 +  CTM_ATTRIB_MAP_7      = 0x0806, ///< Per vertex attribute map 7 (float array).
  26.256 +  CTM_ATTRIB_MAP_8      = 0x0807  ///< Per vertex attribute map 8 (float array).
  26.257 +} CTMenum;
  26.258 +
  26.259 +/// Stream read() function pointer.
  26.260 +/// @param[in] aBuf Pointer to the memory buffer to which data should be read.
  26.261 +/// @param[in] aCount The number of bytes to read.
  26.262 +/// @param[in] aUserData The custom user data that was passed to the
  26.263 +///            ctmLoadCustom() function.
  26.264 +/// @return The number of bytes actually read (if this is less than aCount, it
  26.265 +///         indicates that an error occured or the end of file was reached
  26.266 +///         before all bytes were read).
  26.267 +typedef CTMuint (CTMCALL * CTMreadfn)(void * aBuf, CTMuint aCount, void * aUserData);
  26.268 +
  26.269 +/// Stream write() function pointer.
  26.270 +/// @param[in] aBuf Pointer to the memory buffer from which data should be written.
  26.271 +/// @param[in] aCount The number of bytes to write.
  26.272 +/// @param[in] aUserData The custom user data that was passed to the
  26.273 +///            ctmSaveCustom() function.
  26.274 +/// @return The number of bytes actually written (if this is less than aCount, it
  26.275 +///         indicates that an error occured).
  26.276 +typedef CTMuint (CTMCALL * CTMwritefn)(const void * aBuf, CTMuint aCount, void * aUserData);
  26.277 +
  26.278 +/// Create a new OpenCTM context. The context is used for all subsequent
  26.279 +/// OpenCTM function calls. Several contexts can coexist at the same time.
  26.280 +/// @param[in] aMode An OpenCTM context mode. Set this to CTM_IMPORT if the
  26.281 +///            context will be used for importing data, or set it to CTM_EXPORT
  26.282 +///            if it will be used for exporting data.
  26.283 +/// @return An OpenCTM context handle (or NULL if no context could be created).
  26.284 +CTMEXPORT CTMcontext CTMCALL ctmNewContext(CTMenum aMode);
  26.285 +
  26.286 +/// Free an OpenCTM context.
  26.287 +/// @param[in] aContext An OpenCTM context that has been created by
  26.288 +///            ctmNewContext().
  26.289 +/// @see ctmNewContext()
  26.290 +CTMEXPORT void CTMCALL ctmFreeContext(CTMcontext aContext);
  26.291 +
  26.292 +/// Returns the latest error. Calling this function will return the last
  26.293 +/// produced error code, or CTM_NO_ERROR (zero) if no error has occured since
  26.294 +/// the last call to ctmGetError(). When this function is called, the internal
  26.295 +/// error varibale will be reset to CTM_NONE.
  26.296 +/// @param[in] aContext An OpenCTM context that has been created by
  26.297 +///            ctmNewContext().
  26.298 +/// @return An OpenCTM error code.
  26.299 +/// @see CTMenum
  26.300 +CTMEXPORT CTMenum CTMCALL ctmGetError(CTMcontext aContext);
  26.301 +
  26.302 +/// Converts an OpenCTM error code to a zero-terminated string. 
  26.303 +/// @param[in] aError An OpenCTM error code, as returned by ctmGetError().
  26.304 +/// @return A zero terminated string that describes the error. For instance,
  26.305 +///         if \c aError is CTM_INVALID_OPERATION, then the return value will
  26.306 +///         be "CTM_INVALID_OPERATION".
  26.307 +/// @see CTMenum
  26.308 +CTMEXPORT const char * CTMCALL ctmErrorString(CTMenum aError);
  26.309 +
  26.310 +/// Get information about an OpenCTM context.
  26.311 +/// @param[in] aContext An OpenCTM context that has been created by
  26.312 +///            ctmNewContext().
  26.313 +/// @param[in] aProperty Which property to return.
  26.314 +/// @return An integer value, representing the OpenCTM context property given
  26.315 +///         by \c aProperty.
  26.316 +/// @see CTMenum
  26.317 +CTMEXPORT CTMuint CTMCALL ctmGetInteger(CTMcontext aContext, CTMenum aProperty);
  26.318 +
  26.319 +/// Get information about an OpenCTM context.
  26.320 +/// @param[in] aContext An OpenCTM context that has been created by
  26.321 +///            ctmNewContext().
  26.322 +/// @param[in] aProperty Which property to return.
  26.323 +/// @return A floating point value, representing the OpenCTM context property
  26.324 +///         given by \c aProperty.
  26.325 +/// @see CTMenum
  26.326 +CTMEXPORT CTMfloat CTMCALL ctmGetFloat(CTMcontext aContext, CTMenum aProperty);
  26.327 +
  26.328 +/// Get an integer array from an OpenCTM context.
  26.329 +/// @param[in] aContext An OpenCTM context that has been created by
  26.330 +///             ctmNewContext().
  26.331 +/// @param[in] aProperty Which array to return.
  26.332 +/// @return An integer array. If the requested array does not exist, or
  26.333 +///         if \c aProperty does not indicate an integer array, the function
  26.334 +///         returns NULL.
  26.335 +/// @note The array is only valid as long as the OpenCTM context is valid, or
  26.336 +///       until the corresponding array changes within the OpenCTM context.
  26.337 +///       Trying to access an invalid array will result in undefined
  26.338 +///       behaviour. Therefor it is recommended that the array is copied to
  26.339 +///       a new variable if it is to be used other than directly after the call
  26.340 +///       to ctmGetIntegerArray().
  26.341 +/// @see CTMenum
  26.342 +CTMEXPORT const CTMuint * CTMCALL ctmGetIntegerArray(CTMcontext aContext,
  26.343 +  CTMenum aProperty);
  26.344 +
  26.345 +/// Get a floating point array from an OpenCTM context.
  26.346 +/// @param[in] aContext An OpenCTM context that has been created by
  26.347 +///            ctmNewContext().
  26.348 +/// @param[in] aProperty Which array to return.
  26.349 +/// @return A floating point array. If the requested array does not exist, or
  26.350 +///         if \c aProperty does not indicate a float array, the function
  26.351 +///         returns NULL.
  26.352 +/// @note The array is only valid as long as the OpenCTM context is valid, or
  26.353 +///       until the corresponding array changes within the OpenCTM context.
  26.354 +///       Trying to access an invalid array will result in undefined
  26.355 +///       behaviour. Therefor it is recommended that the array is copied to
  26.356 +///       a new variable if it is to be used other than directly after the call
  26.357 +///       to ctmGetFloatArray().
  26.358 +/// @see CTMenum
  26.359 +CTMEXPORT const CTMfloat * CTMCALL ctmGetFloatArray(CTMcontext aContext,
  26.360 +  CTMenum aProperty);
  26.361 +
  26.362 +/// Get a reference to the named UV map.
  26.363 +/// @param[in] aContext An OpenCTM context that has been created by
  26.364 +///            ctmNewContext().
  26.365 +/// @param[in] aName The name of the UV map that should be returned.
  26.366 +/// @return A reference to a UV map. If the UV map was found, a value of
  26.367 +///         CTM_UV_MAP_1 or higher is returned, otherwise CTM_NONE is
  26.368 +///         returned.
  26.369 +CTMEXPORT CTMenum CTMCALL ctmGetNamedUVMap(CTMcontext aContext,
  26.370 +  const char * aName);
  26.371 +
  26.372 +/// Get information about a UV map.
  26.373 +/// @param[in] aContext An OpenCTM context that has been created by
  26.374 +///            ctmNewContext().
  26.375 +/// @param[in] aUVMap Which UV map to query (CTM_UV_MAP_1 or higher).
  26.376 +/// @param[in] aProperty Which UV map property to return.
  26.377 +/// @return A string value, representing the UV map property given
  26.378 +///         by \c aProperty.
  26.379 +/// @note The string is only valid as long as the UV map within the OpenCTM
  26.380 +///       context is valid. Trying to access an invalid string will result in
  26.381 +///       undefined behaviour. Therefor it is recommended that the string is
  26.382 +///       copied to a new variable if it is to be used other than directly after
  26.383 +///       the call to ctmGetUVMapString().
  26.384 +/// @see CTMenum
  26.385 +CTMEXPORT const char * CTMCALL ctmGetUVMapString(CTMcontext aContext,
  26.386 +  CTMenum aUVMap, CTMenum aProperty);
  26.387 +
  26.388 +/// Get information about a UV map.
  26.389 +/// @param[in] aContext An OpenCTM context that has been created by
  26.390 +///            ctmNewContext().
  26.391 +/// @param[in] aUVMap Which UV map to query (CTM_UV_MAP_1 or higher).
  26.392 +/// @param[in] aProperty Which UV map property to return.
  26.393 +/// @return A floating point value, representing the UV map property given
  26.394 +///         by \c aProperty.
  26.395 +/// @see CTMenum
  26.396 +CTMEXPORT CTMfloat CTMCALL ctmGetUVMapFloat(CTMcontext aContext,
  26.397 +  CTMenum aUVMap, CTMenum aProperty);
  26.398 +
  26.399 +/// Get a reference to the named vertex attribute map.
  26.400 +/// @param[in] aContext An OpenCTM context that has been created by
  26.401 +///            ctmNewContext().
  26.402 +/// @param[in] aName The name of the attribute map that should be returned.
  26.403 +/// @return A reference to an attribute map. If the attribute map was found,
  26.404 +///         a value of CTM_ATTRIB_MAP_1 or higher is returned, otherwise
  26.405 +///         CTM_NONE is returned.
  26.406 +CTMEXPORT CTMenum CTMCALL ctmGetNamedAttribMap(CTMcontext aContext,
  26.407 +  const char * aName);
  26.408 +
  26.409 +/// Get information about a vertex attribute map.
  26.410 +/// @param[in] aContext An OpenCTM context that has been created by
  26.411 +///            ctmNewContext().
  26.412 +/// @param[in] aAttribMap Which vertex attribute map to query (CTM_ATTRIB_MAP_1
  26.413 +///            or higher).
  26.414 +/// @param[in] aProperty Which vertex attribute map property to return.
  26.415 +/// @return A string value, representing the vertex attribute map property given
  26.416 +///         by \c aProperty.
  26.417 +/// @note The string is only valid as long as the vertex attribute map within
  26.418 +///       the OpenCTM context is valid. Trying to access an invalid string will
  26.419 +///       result in undefined behaviour. Therefor it is recommended that the
  26.420 +///       string is copied to a new variable if it is to be used other than
  26.421 +///       directly after the call to ctmGetAttribMapString().
  26.422 +/// @see CTMenum
  26.423 +CTMEXPORT const char * CTMCALL ctmGetAttribMapString(CTMcontext aContext,
  26.424 +  CTMenum aAttribMap, CTMenum aProperty);
  26.425 +
  26.426 +/// Get information about a vertex attribute map.
  26.427 +/// @param[in] aContext An OpenCTM context that has been created by
  26.428 +///            ctmNewContext().
  26.429 +/// @param[in] aAttribMap Which vertex attribute map to query (CTM_ATTRIB_MAP_1
  26.430 +///            or higher).
  26.431 +/// @param[in] aProperty Which vertex attribute map property to return.
  26.432 +/// @return A floating point value, representing the vertex attribute map
  26.433 +///         property given by \c aProperty.
  26.434 +/// @see CTMenum
  26.435 +CTMEXPORT CTMfloat CTMCALL ctmGetAttribMapFloat(CTMcontext aContext,
  26.436 +  CTMenum aAttribMap, CTMenum aProperty);
  26.437 +
  26.438 +/// Get information about an OpenCTM context.
  26.439 +/// @param[in] aContext An OpenCTM context that has been created by
  26.440 +///            ctmNewContext().
  26.441 +/// @param[in] aProperty Which property to return.
  26.442 +/// @return A string value, representing the OpenCTM context property given
  26.443 +///         by \c aProperty.
  26.444 +/// @note The string is only valid as long as the OpenCTM context is valid, or
  26.445 +///       until the corresponding string changes within the OpenCTM context
  26.446 +///       (e.g. calling ctmFileComment() invalidates the CTM_FILE_COMMENT
  26.447 +///       string). Trying to access an invalid string will result in undefined
  26.448 +///       behaviour. Therefor it is recommended that the string is copied to
  26.449 +///       a new variable if it is to be used other than directly after the call
  26.450 +///       to ctmGetString().
  26.451 +/// @see CTMenum
  26.452 +CTMEXPORT const char * CTMCALL ctmGetString(CTMcontext aContext,
  26.453 +  CTMenum aProperty);
  26.454 +
  26.455 +/// Set which compression method to use for the given OpenCTM context.
  26.456 +/// The selected compression method will be used when calling the ctmSave()
  26.457 +/// function.
  26.458 +/// @param[in] aContext An OpenCTM context that has been created by
  26.459 +///            ctmNewContext().
  26.460 +/// @param[in] aMethod Which compression method to use: CTM_METHOD_RAW,
  26.461 +///            CTM_METHOD_MG1 or CTM_METHOD_MG2 (the default method is
  26.462 +///            CTM_METHOD_MG1).
  26.463 +/// @see CTM_METHOD_RAW, CTM_METHOD_MG1, CTM_METHOD_MG2
  26.464 +CTMEXPORT void CTMCALL ctmCompressionMethod(CTMcontext aContext,
  26.465 +  CTMenum aMethod);
  26.466 +
  26.467 +/// Set which LZMA compression level to use for the given OpenCTM context.
  26.468 +/// The compression level can be between 0 (fastest) and 9 (best). The higher
  26.469 +/// the compression level, the more memory is required for compression and
  26.470 +/// decompression. The default compression level is 1.
  26.471 +/// @param[in] aContext An OpenCTM context that has been created by
  26.472 +///            ctmNewContext().
  26.473 +/// @param[in] aLevel Which compression level to use (0 to 9).
  26.474 +CTMEXPORT void CTMCALL ctmCompressionLevel(CTMcontext aContext,
  26.475 +  CTMuint aLevel);
  26.476 +
  26.477 +/// Set the vertex coordinate precision (only used by the MG2 compression
  26.478 +/// method).
  26.479 +/// @param[in] aContext An OpenCTM context that has been created by
  26.480 +///            ctmNewContext().
  26.481 +/// @param[in] aPrecision Fixed point precision. For instance, if this value is
  26.482 +///            0.001, all vertex coordinates will be rounded to three decimals.
  26.483 +///            The default vertex coordinate precision is 2^-10 ~= 0.00098.
  26.484 +CTMEXPORT void CTMCALL ctmVertexPrecision(CTMcontext aContext,
  26.485 +  CTMfloat aPrecision);
  26.486 +
  26.487 +/// Set the vertex coordinate precision, relative to the mesh dimensions (only
  26.488 +/// used by the MG2 compression method).
  26.489 +/// @param[in] aContext An OpenCTM context that has been created by
  26.490 +///            ctmNewContext().
  26.491 +/// @param[in] aRelPrecision Relative precision. This factor is multiplied by the
  26.492 +///            average triangle edge length in the mesh in order to obtain the
  26.493 +///            final, fixed point precision. For instance, if aRelPrecision is 
  26.494 +///            0.01, and the average edge length is 3.7, then the fixed point
  26.495 +///            precision is set to 0.037.
  26.496 +/// @note The mesh must have been defined using the ctmDefineMesh() function
  26.497 +///       before calling this function.
  26.498 +/// @see ctmVertexPrecision().
  26.499 +CTMEXPORT void CTMCALL ctmVertexPrecisionRel(CTMcontext aContext,
  26.500 +  CTMfloat aRelPrecision);
  26.501 +
  26.502 +/// Set the normal precision (only used by the MG2 compression method). The
  26.503 +/// normal is represented in spherical coordinates in the MG2 compression
  26.504 +/// method, and the normal precision controls the angular and radial resolution.
  26.505 +/// @param[in] aContext An OpenCTM context that has been created by
  26.506 +///            ctmNewContext().
  26.507 +/// @param[in] aPrecision Fixed point precision. For the angular information,
  26.508 +///            this value represents the angular precision. For the radial
  26.509 +///            information, this value is the linear resolution. For instance,
  26.510 +///            0.01 means that the circle is divided into 100 steps, and the
  26.511 +///            normal magnitude is rounded to 2 decimals. The default normal
  26.512 +///            precision is 2^-8 ~= 0.0039.
  26.513 +CTMEXPORT void CTMCALL ctmNormalPrecision(CTMcontext aContext,
  26.514 +  CTMfloat aPrecision);
  26.515 +
  26.516 +/// Set the coordinate precision for the specified UV map (only used by the
  26.517 +/// MG2 compression method).
  26.518 +/// @param[in] aContext An OpenCTM context that has been created by
  26.519 +///            ctmNewContext().
  26.520 +/// @param[in] aUVMap A UV map specifier for a defined UV map
  26.521 +///            (CTM_UV_MAP_1, ...).
  26.522 +/// @param[in] aPrecision Fixed point precision. For instance, if this value is
  26.523 +///            0.001, all UV coordinates will be rounded to three decimals.
  26.524 +///            The default UV coordinate precision is 2^-12 ~= 0.00024.
  26.525 +/// @see ctmAddUVMap().
  26.526 +CTMEXPORT void CTMCALL ctmUVCoordPrecision(CTMcontext aContext,
  26.527 +  CTMenum aUVMap, CTMfloat aPrecision);
  26.528 +
  26.529 +/// Set the attribute value precision for the specified attribute map (only
  26.530 +/// used by the MG2 compression method).
  26.531 +/// @param[in] aContext An OpenCTM context that has been created by
  26.532 +///            ctmNewContext().
  26.533 +/// @param[in] aAttribMap An attribute map specifier for a defined attribute map
  26.534 +///            (CTM_ATTRIB_MAP_1, ...).
  26.535 +/// @param[in] aPrecision Fixed point precision. For instance, if this value is
  26.536 +///            0.001, all attribute values will be rounded to three decimals.
  26.537 +///            If the attributes represent integer values, set the precision
  26.538 +///            to 1.0. The default attribute precision is 2^-8 ~= 0.0039.
  26.539 +/// @see ctmAddAttribMap().
  26.540 +CTMEXPORT void CTMCALL ctmAttribPrecision(CTMcontext aContext,
  26.541 +  CTMenum aAttribMap, CTMfloat aPrecision);
  26.542 +
  26.543 +/// Set the file comment for the given OpenCTM context.
  26.544 +/// @param[in] aContext An OpenCTM context that has been created by
  26.545 +///            ctmNewContext().
  26.546 +/// @param[in] aFileComment The file comment (zero terminated UTF-8 string).
  26.547 +CTMEXPORT void CTMCALL ctmFileComment(CTMcontext aContext,
  26.548 +  const char * aFileComment);
  26.549 +
  26.550 +/// Define a triangle mesh.
  26.551 +/// @param[in] aContext An OpenCTM context that has been created by
  26.552 +///            ctmNewContext().
  26.553 +/// @param[in] aVertices An array of vertices (three consecutive floats make
  26.554 +///            one vertex).
  26.555 +/// @param[in] aVertexCount The number of vertices in \c aVertices (and
  26.556 +///            optionally \c aTexCoords).
  26.557 +/// @param[in] aIndices An array of vertex indices (three consecutive integers
  26.558 +///            make one triangle).
  26.559 +/// @param[in] aTriangleCount The number of triangles in \c aIndices (there
  26.560 +///            must be exactly 3 x \c aTriangleCount indices in \c aIndices).
  26.561 +/// @param[in] aNormals An array of per-vertex normals (or NULL if there are
  26.562 +///            no normals). Each normal is made up by three consecutive floats,
  26.563 +///            and there must be \c aVertexCount normals.
  26.564 +/// @see ctmAddUVMap(), ctmAddAttribMap(), ctmSave(), ctmSaveCustom().
  26.565 +CTMEXPORT void CTMCALL ctmDefineMesh(CTMcontext aContext,
  26.566 +  const CTMfloat * aVertices, CTMuint aVertexCount, const CTMuint * aIndices,
  26.567 +  CTMuint aTriangleCount, const CTMfloat * aNormals);
  26.568 +
  26.569 +/// Define a UV map. There can be several UV maps in a mesh. A UV map is
  26.570 +/// typically used for 2D texture mapping.
  26.571 +/// @param[in] aContext An OpenCTM context that has been created by
  26.572 +///            ctmNewContext().
  26.573 +/// @param[in] aUVCoords An array of UV coordinates. Each UV coordinate is made
  26.574 +///            up by two consecutive floats, and there must be as many
  26.575 +///            coordinates as there are vertices in the mesh.
  26.576 +/// @param[in] aName A unique name for this UV map (zero terminated UTF-8
  26.577 +///            string).
  26.578 +/// @param[in] aFileName A reference to a image file (zero terminated
  26.579 +///            UTF-8 string). If no file name reference exists, pass NULL.
  26.580 +/// @return A UV map index (CTM_UV_MAP_1 and higher). If the function
  26.581 +///         failed, it will return the zero valued CTM_NONE (use ctmGetError()
  26.582 +///         to determine the cause of the error).
  26.583 +/// @note A triangle mesh must have been defined before calling this function,
  26.584 +///       since the number of vertices is defined by the triangle mesh.
  26.585 +/// @see ctmDefineMesh().
  26.586 +CTMEXPORT CTMenum CTMCALL ctmAddUVMap(CTMcontext aContext,
  26.587 +  const CTMfloat * aUVCoords, const char * aName, const char * aFileName);
  26.588 +
  26.589 +/// Define a custom vertex attribute map. Custom vertex attributes can be used
  26.590 +/// for defining special per-vertex attributes, such as color, weight, ambient
  26.591 +/// occlusion factor, etc.
  26.592 +/// @param[in] aContext An OpenCTM context that has been created by
  26.593 +///            ctmNewContext().
  26.594 +/// @param[in] aAttribValues An array of attribute values. Each attribute value
  26.595 +///            is made up by four consecutive floats, and there must be as many
  26.596 +///            values as there are vertices in the mesh.
  26.597 +/// @param[in] aName A unique name for this attribute map (zero terminated UTF-8
  26.598 +///            string).
  26.599 +/// @return A attribute map index (CTM_ATTRIB_MAP_1 and higher). If the function
  26.600 +///         failed, it will return the zero valued CTM_NONE (use ctmGetError()
  26.601 +///         to determine the cause of the error).
  26.602 +/// @note A triangle mesh must have been defined before calling this function,
  26.603 +///       since the number of vertices is defined by the triangle mesh.
  26.604 +/// @see ctmDefineMesh().
  26.605 +CTMEXPORT CTMenum CTMCALL ctmAddAttribMap(CTMcontext aContext,
  26.606 +  const CTMfloat * aAttribValues, const char * aName);
  26.607 +
  26.608 +/// Load an OpenCTM format file into the context. The mesh data can be retrieved
  26.609 +/// with the various ctmGet functions.
  26.610 +/// @param[in] aContext An OpenCTM context that has been created by
  26.611 +///            ctmNewContext().
  26.612 +/// @param[in] aFileName The name of the file to be loaded.
  26.613 +CTMEXPORT void CTMCALL ctmLoad(CTMcontext aContext, const char * aFileName);
  26.614 +
  26.615 +/// Load an OpenCTM format file using a custom stream read function. The mesh
  26.616 +/// data can be retrieved with the various ctmGet functions.
  26.617 +/// @param[in] aContext An OpenCTM context that has been created by
  26.618 +///            ctmNewContext().
  26.619 +/// @param[in] aReadFn Pointer to a custom stream read function.
  26.620 +/// @param[in] aUserData Custom user data, which can be a C language FILE
  26.621 +///            handle, C++ istream object, or a custom object pointer
  26.622 +///            of any type. The user data pointer will be passed to the
  26.623 +///            custom stream read function.
  26.624 +/// @see CTMreadfn.
  26.625 +CTMEXPORT void CTMCALL ctmLoadCustom(CTMcontext aContext, CTMreadfn aReadFn,
  26.626 +  void * aUserData);
  26.627 +
  26.628 +/// Save an OpenCTM format file. The mesh must have been defined by
  26.629 +/// ctmDefineMesh().
  26.630 +/// @param[in] aContext An OpenCTM context that has been created by
  26.631 +///            ctmNewContext().
  26.632 +/// @param[in] aFileName The name of the file to be saved.
  26.633 +CTMEXPORT void CTMCALL ctmSave(CTMcontext aContext, const char * aFileName);
  26.634 +
  26.635 +/// Save an OpenCTM format file using a custom stream write function. The mesh
  26.636 +/// must have been defined by ctmDefineMesh().
  26.637 +/// @param[in] aContext An OpenCTM context that has been created by
  26.638 +///            ctmNewContext().
  26.639 +/// @param[in] aWriteFn Pointer to a custom stream write function.
  26.640 +/// @param[in] aUserData Custom user data, which can be a C language FILE
  26.641 +///            handle, C++ ostream object, or a custom object pointer
  26.642 +///            of any type. The user data pointer will be passed to the
  26.643 +///            custom stream write function.
  26.644 +/// @see CTMwritefn.
  26.645 +CTMEXPORT void CTMCALL ctmSaveCustom(CTMcontext aContext, CTMwritefn aWriteFn,
  26.646 +  void * aUserData);
  26.647 +
  26.648 +#ifdef __cplusplus
  26.649 +}
  26.650 +#endif
  26.651 +
  26.652 +
  26.653 +// C++ extensions to the API (to disable C++ extensions, define OPENCTM_NO_CPP)
  26.654 +#if defined(__cplusplus) && !defined(OPENCTM_NO_CPP)
  26.655 +  #include "openctmpp.h"
  26.656 +#endif
  26.657 +
  26.658 +#endif // __OPENCTM_H_
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/libs/openctm/openctmpp.h	Thu Sep 26 04:47:05 2013 +0300
    27.3 @@ -0,0 +1,377 @@
    27.4 +//-----------------------------------------------------------------------------
    27.5 +// Product:     OpenCTM
    27.6 +// File:        openctmpp.h
    27.7 +// Description: C++ wrapper for the OpenCTM API.
    27.8 +//-----------------------------------------------------------------------------
    27.9 +// Copyright (c) 2009-2010 Marcus Geelnard
   27.10 +//
   27.11 +// This software is provided 'as-is', without any express or implied
   27.12 +// warranty. In no event will the authors be held liable for any damages
   27.13 +// arising from the use of this software.
   27.14 +//
   27.15 +// Permission is granted to anyone to use this software for any purpose,
   27.16 +// including commercial applications, and to alter it and redistribute it
   27.17 +// freely, subject to the following restrictions:
   27.18 +//
   27.19 +//     1. The origin of this software must not be misrepresented; you must not
   27.20 +//     claim that you wrote the original software. If you use this software
   27.21 +//     in a product, an acknowledgment in the product documentation would be
   27.22 +//     appreciated but is not required.
   27.23 +//
   27.24 +//     2. Altered source versions must be plainly marked as such, and must not
   27.25 +//     be misrepresented as being the original software.
   27.26 +//
   27.27 +//     3. This notice may not be removed or altered from any source
   27.28 +//     distribution.
   27.29 +//-----------------------------------------------------------------------------
   27.30 +
   27.31 +// To disable C++ extensions, define OPENCTM_NO_CPP
   27.32 +#ifndef OPENCTM_NO_CPP
   27.33 +
   27.34 +#ifndef __OPENCTMPP_H_
   27.35 +#define __OPENCTMPP_H_
   27.36 +
   27.37 +// Just in case (if this file was included from outside openctm.h)...
   27.38 +#ifndef __OPENCTM_H_
   27.39 +#include "openctm.h"
   27.40 +#endif
   27.41 +
   27.42 +#include <exception>
   27.43 +
   27.44 +/// OpenCTM exception. When an error occurs, a \c ctm_error exception is
   27.45 +/// thrown. Its what() function returns the name of the OpenCTM error code
   27.46 +/// (for instance "CTM_INVALID_OPERATION").
   27.47 +class ctm_error: public std::exception
   27.48 +{
   27.49 +  private:
   27.50 +    CTMenum mErrorCode;
   27.51 +
   27.52 +  public:
   27.53 +    explicit ctm_error(CTMenum aError)
   27.54 +    {
   27.55 +      mErrorCode = aError;
   27.56 +    }
   27.57 +
   27.58 +    virtual const char* what() const throw()
   27.59 +    {
   27.60 +      return ctmErrorString(mErrorCode);
   27.61 +    }
   27.62 +
   27.63 +    CTMenum error_code() const throw()
   27.64 +    {
   27.65 +      return mErrorCode;
   27.66 +    }
   27.67 +};
   27.68 +
   27.69 +
   27.70 +/// OpenCTM importer class. This is a C++ wrapper class for an OpenCTM import
   27.71 +/// context. Usage example:
   27.72 +///
   27.73 +/// @code
   27.74 +///   // Create a new OpenCTM importer object
   27.75 +///   CTMimporter ctm;
   27.76 +///
   27.77 +///   // Load the OpenCTM file
   27.78 +///   ctm.Load("mymesh.ctm");
   27.79 +///
   27.80 +///   // Access the mesh data
   27.81 +///   vertCount = ctm.GetInteger(CTM_VERTEX_COUNT);
   27.82 +///   vertices = ctm.GetFloatArray(CTM_VERTICES);
   27.83 +///   triCount = ctm.GetInteger(CTM_TRIANGLE_COUNT);
   27.84 +///   indices = ctm.GetIntegerArray(CTM_INDICES);
   27.85 +///
   27.86 +///   // Deal with the mesh (e.g. transcode it to our internal representation)
   27.87 +///   // ...
   27.88 +/// @endcode
   27.89 +
   27.90 +class CTMimporter {
   27.91 +  private:
   27.92 +    /// The OpenCTM context handle.
   27.93 +    CTMcontext mContext;
   27.94 +
   27.95 +    /// Check for OpenCTM errors, and throw an exception if an error has
   27.96 +    /// occured.
   27.97 +    void CheckError()
   27.98 +    {
   27.99 +      CTMenum err = ctmGetError(mContext);
  27.100 +      if(err != CTM_NONE)
  27.101 +        throw ctm_error(err);
  27.102 +    }
  27.103 +
  27.104 +  public:
  27.105 +    /// Constructor
  27.106 +    CTMimporter()
  27.107 +    {
  27.108 +      mContext = ctmNewContext(CTM_IMPORT);
  27.109 +    }
  27.110 +
  27.111 +    /// Destructor
  27.112 +    ~CTMimporter()
  27.113 +    {
  27.114 +      ctmFreeContext(mContext);
  27.115 +    }
  27.116 +
  27.117 +    /// Wrapper for ctmGetInteger()
  27.118 +    CTMuint GetInteger(CTMenum aProperty)
  27.119 +    {
  27.120 +      CTMuint res = ctmGetInteger(mContext, aProperty);
  27.121 +      CheckError();
  27.122 +      return res;
  27.123 +    }
  27.124 +
  27.125 +    /// Wrapper for ctmGetFloat()
  27.126 +    CTMfloat GetFloat(CTMenum aProperty)
  27.127 +    {
  27.128 +      CTMfloat res = ctmGetFloat(mContext, aProperty);
  27.129 +      CheckError();
  27.130 +      return res;
  27.131 +    }
  27.132 +
  27.133 +    /// Wrapper for ctmGetIntegerArray()
  27.134 +    const CTMuint * GetIntegerArray(CTMenum aProperty)
  27.135 +    {
  27.136 +      const CTMuint * res = ctmGetIntegerArray(mContext, aProperty);
  27.137 +      CheckError();
  27.138 +      return res;
  27.139 +    }
  27.140 +
  27.141 +    /// Wrapper for ctmGetFloatArray()
  27.142 +    const CTMfloat * GetFloatArray(CTMenum aProperty)
  27.143 +    {
  27.144 +      const CTMfloat * res = ctmGetFloatArray(mContext, aProperty);
  27.145 +      CheckError();
  27.146 +      return res;
  27.147 +    }
  27.148 +
  27.149 +    /// Wrapper for ctmGetNamedUVMap()
  27.150 +    CTMenum GetNamedUVMap(const char * aName)
  27.151 +    {
  27.152 +      CTMenum res = ctmGetNamedUVMap(mContext, aName);
  27.153 +      CheckError();
  27.154 +      return res;
  27.155 +    }
  27.156 +
  27.157 +    /// Wrapper for ctmGetUVMapString()
  27.158 +    const char * GetUVMapString(CTMenum aUVMap, CTMenum aProperty)
  27.159 +    {
  27.160 +      const char * res = ctmGetUVMapString(mContext, aUVMap, aProperty);
  27.161 +      CheckError();
  27.162 +      return res;
  27.163 +    }
  27.164 +
  27.165 +    /// Wrapper for ctmGetUVMapFloat()
  27.166 +    CTMfloat GetUVMapFloat(CTMenum aUVMap, CTMenum aProperty)
  27.167 +    {
  27.168 +      CTMfloat res = ctmGetUVMapFloat(mContext, aUVMap, aProperty);
  27.169 +      CheckError();
  27.170 +      return res;
  27.171 +    }
  27.172 +
  27.173 +    /// Wrapper for ctmGetNamedAttribMap()
  27.174 +    CTMenum GetNamedAttribMap(const char * aName)
  27.175 +    {
  27.176 +      CTMenum res = ctmGetNamedAttribMap(mContext, aName);
  27.177 +      CheckError();
  27.178 +      return res;
  27.179 +    }
  27.180 +
  27.181 +    /// Wrapper for ctmGetAttribMapString()
  27.182 +    const char * GetAttribMapString(CTMenum aAttribMap, CTMenum aProperty)
  27.183 +    {
  27.184 +      const char * res = ctmGetAttribMapString(mContext, aAttribMap, aProperty);
  27.185 +      CheckError();
  27.186 +      return res;
  27.187 +    }
  27.188 +
  27.189 +    /// Wrapper for ctmGetAttribMapFloat()
  27.190 +    CTMfloat GetAttribMapFloat(CTMenum aAttribMap, CTMenum aProperty)
  27.191 +    {
  27.192 +      CTMfloat res = ctmGetAttribMapFloat(mContext, aAttribMap, aProperty);
  27.193 +      CheckError();
  27.194 +      return res;
  27.195 +    }
  27.196 +
  27.197 +    /// Wrapper for ctmGetString()
  27.198 +    const char * GetString(CTMenum aProperty)
  27.199 +    {
  27.200 +      const char * res = ctmGetString(mContext, aProperty);
  27.201 +      CheckError();
  27.202 +      return res;
  27.203 +    }
  27.204 +
  27.205 +    /// Wrapper for ctmLoad()
  27.206 +    void Load(const char * aFileName)
  27.207 +    {
  27.208 +      ctmLoad(mContext, aFileName);
  27.209 +      CheckError();
  27.210 +    }
  27.211 +
  27.212 +    /// Wrapper for ctmLoadCustom()
  27.213 +    void LoadCustom(CTMreadfn aReadFn, void * aUserData)
  27.214 +    {
  27.215 +      ctmLoadCustom(mContext, aReadFn, aUserData);
  27.216 +      CheckError();
  27.217 +    }
  27.218 +
  27.219 +    // You can not copy nor assign from one CTMimporter object to another, since
  27.220 +    // the object contains hidden state. By declaring these dummy prototypes
  27.221 +    // without an implementation, you will at least get linker errors if you try
  27.222 +    // to copy or assign a CTMimporter object.
  27.223 +    CTMimporter(const CTMimporter& v);
  27.224 +    CTMimporter& operator=(const CTMimporter& v);
  27.225 +};
  27.226 +
  27.227 +
  27.228 +/// OpenCTM exporter class. This is a C++ wrapper class for an OpenCTM export
  27.229 +/// context. Usage example:
  27.230 +/// @code
  27.231 +/// void MySaveFile(CTMuint aVertCount, CTMuint aTriCount, CTMfloat * aVertices,
  27.232 +///   CTMuint * aIndices, const char * aFileName)
  27.233 +/// {
  27.234 +///   // Create a new OpenCTM exporter object
  27.235 +///   CTMexporter ctm;
  27.236 +///
  27.237 +///   // Define our mesh representation to OpenCTM (store references to it in
  27.238 +///   // the context)
  27.239 +///   ctm.DefineMesh(aVertices, aVertCount, aIndices, aTriCount, NULL);
  27.240 +///
  27.241 +///   // Save the OpenCTM file
  27.242 +///   ctm.Save(aFileName);
  27.243 +/// }
  27.244 +/// @endcode
  27.245 +
  27.246 +class CTMexporter {
  27.247 +  private:
  27.248 +    /// The OpenCTM context handle.
  27.249 +    CTMcontext mContext;
  27.250 +
  27.251 +    /// Check for OpenCTM errors, and throw an exception if an error has
  27.252 +    /// occured.
  27.253 +    void CheckError()
  27.254 +    {
  27.255 +      CTMenum err = ctmGetError(mContext);
  27.256 +      if(err != CTM_NONE)
  27.257 +        throw ctm_error(err);
  27.258 +    }
  27.259 +
  27.260 +  public:
  27.261 +    /// Constructor
  27.262 +    CTMexporter()
  27.263 +    {
  27.264 +      mContext = ctmNewContext(CTM_EXPORT);
  27.265 +    }
  27.266 +
  27.267 +    /// Destructor
  27.268 +    ~CTMexporter()
  27.269 +    {
  27.270 +      ctmFreeContext(mContext);
  27.271 +    }
  27.272 +
  27.273 +    /// Wrapper for ctmCompressionMethod()
  27.274 +    void CompressionMethod(CTMenum aMethod)
  27.275 +    {
  27.276 +      ctmCompressionMethod(mContext, aMethod);
  27.277 +      CheckError();
  27.278 +    }
  27.279 +
  27.280 +    /// Wrapper for ctmCompressionLevel()
  27.281 +    void CompressionLevel(CTMuint aLevel)
  27.282 +    {
  27.283 +      ctmCompressionLevel(mContext, aLevel);
  27.284 +      CheckError();
  27.285 +    }
  27.286 +
  27.287 +    /// Wrapper for ctmVertexPrecision()
  27.288 +    void VertexPrecision(CTMfloat aPrecision)
  27.289 +    {
  27.290 +      ctmVertexPrecision(mContext, aPrecision);
  27.291 +      CheckError();
  27.292 +    }
  27.293 +
  27.294 +    /// Wrapper for ctmVertexPrecisionRel()
  27.295 +    void VertexPrecisionRel(CTMfloat aRelPrecision)
  27.296 +    {
  27.297 +      ctmVertexPrecisionRel(mContext, aRelPrecision);
  27.298 +      CheckError();
  27.299 +    }
  27.300 +
  27.301 +    /// Wrapper for ctmNormalPrecision()
  27.302 +    void NormalPrecision(CTMfloat aPrecision)
  27.303 +    {
  27.304 +      ctmNormalPrecision(mContext, aPrecision);
  27.305 +      CheckError();
  27.306 +    }
  27.307 +
  27.308 +    /// Wrapper for ctmUVCoordPrecision()
  27.309 +    void UVCoordPrecision(CTMenum aUVMap, CTMfloat aPrecision)
  27.310 +    {
  27.311 +      ctmUVCoordPrecision(mContext, aUVMap, aPrecision);
  27.312 +      CheckError();
  27.313 +    }
  27.314 +
  27.315 +    /// Wrapper for ctmAttribPrecision()
  27.316 +    void AttribPrecision(CTMenum aAttribMap, CTMfloat aPrecision)
  27.317 +    {
  27.318 +      ctmAttribPrecision(mContext, aAttribMap, aPrecision);
  27.319 +      CheckError();
  27.320 +    }
  27.321 +
  27.322 +    /// Wrapper for ctmFileComment()
  27.323 +    void FileComment(const char * aFileComment)
  27.324 +    {
  27.325 +      ctmFileComment(mContext, aFileComment);
  27.326 +      CheckError();
  27.327 +    }
  27.328 +
  27.329 +    /// Wrapper for ctmDefineMesh()
  27.330 +    void DefineMesh(const CTMfloat * aVertices, CTMuint aVertexCount, 
  27.331 +      const CTMuint * aIndices, CTMuint aTriangleCount,
  27.332 +      const CTMfloat * aNormals)
  27.333 +    {
  27.334 +      ctmDefineMesh(mContext, aVertices, aVertexCount, aIndices, aTriangleCount,
  27.335 +                    aNormals);
  27.336 +      CheckError();
  27.337 +    }
  27.338 +
  27.339 +    /// Wrapper for ctmAddUVMap()
  27.340 +    CTMenum AddUVMap(const CTMfloat * aUVCoords, const char * aName,
  27.341 +      const char * aFileName)
  27.342 +    {
  27.343 +      CTMenum res = ctmAddUVMap(mContext, aUVCoords, aName, aFileName);
  27.344 +      CheckError();
  27.345 +      return res;
  27.346 +    }
  27.347 +
  27.348 +    /// Wrapper for ctmAddAttribMap()
  27.349 +    CTMenum AddAttribMap(const CTMfloat * aAttribValues, const char * aName)
  27.350 +    {
  27.351 +      CTMenum res = ctmAddAttribMap(mContext, aAttribValues, aName);
  27.352 +      CheckError();
  27.353 +      return res;
  27.354 +    }
  27.355 +
  27.356 +    /// Wrapper for ctmSave()
  27.357 +    void Save(const char * aFileName)
  27.358 +    {
  27.359 +      ctmSave(mContext, aFileName);
  27.360 +      CheckError();
  27.361 +    }
  27.362 +
  27.363 +    /// Wrapper for ctmSaveCustom()
  27.364 +    void SaveCustom(CTMwritefn aWriteFn, void * aUserData)
  27.365 +    {
  27.366 +      ctmSaveCustom(mContext, aWriteFn, aUserData);
  27.367 +      CheckError();
  27.368 +    }
  27.369 +
  27.370 +    // You can not copy nor assign from one CTMexporter object to another, since
  27.371 +    // the object contains hidden state. By declaring these dummy prototypes
  27.372 +    // without an implementation, you will at least get linker errors if you try
  27.373 +    // to copy or assign a CTMexporter object.
  27.374 +    CTMexporter(const CTMexporter& v);
  27.375 +    CTMexporter& operator=(const CTMexporter& v);
  27.376 +};
  27.377 +
  27.378 +#endif // __OPENCTMPP_H_
  27.379 +
  27.380 +#endif // OPENCTM_NO_CPP
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/libs/openctm/stream.c	Thu Sep 26 04:47:05 2013 +0300
    28.3 @@ -0,0 +1,512 @@
    28.4 +//-----------------------------------------------------------------------------
    28.5 +// Product:     OpenCTM
    28.6 +// File:        stream.c
    28.7 +// Description: Stream I/O functions.
    28.8 +//-----------------------------------------------------------------------------
    28.9 +// Copyright (c) 2009-2010 Marcus Geelnard
   28.10 +//
   28.11 +// This software is provided 'as-is', without any express or implied
   28.12 +// warranty. In no event will the authors be held liable for any damages
   28.13 +// arising from the use of this software.
   28.14 +//
   28.15 +// Permission is granted to anyone to use this software for any purpose,
   28.16 +// including commercial applications, and to alter it and redistribute it
   28.17 +// freely, subject to the following restrictions:
   28.18 +//
   28.19 +//     1. The origin of this software must not be misrepresented; you must not
   28.20 +//     claim that you wrote the original software. If you use this software
   28.21 +//     in a product, an acknowledgment in the product documentation would be
   28.22 +//     appreciated but is not required.
   28.23 +//
   28.24 +//     2. Altered source versions must be plainly marked as such, and must not
   28.25 +//     be misrepresented as being the original software.
   28.26 +//
   28.27 +//     3. This notice may not be removed or altered from any source
   28.28 +//     distribution.
   28.29 +//-----------------------------------------------------------------------------
   28.30 +
   28.31 +#include <stdlib.h>
   28.32 +#include <string.h>
   28.33 +#include <LzmaLib.h>
   28.34 +#include "openctm.h"
   28.35 +#include "internal.h"
   28.36 +
   28.37 +#ifdef __DEBUG_
   28.38 +#include <stdio.h>
   28.39 +#endif
   28.40 +
   28.41 +//-----------------------------------------------------------------------------
   28.42 +// _ctmStreamRead() - Read data from a stream.
   28.43 +//-----------------------------------------------------------------------------
   28.44 +CTMuint _ctmStreamRead(_CTMcontext * self, void * aBuf, CTMuint aCount)
   28.45 +{
   28.46 +  if(!self->mUserData || !self->mReadFn)
   28.47 +    return 0;
   28.48 +
   28.49 +  return self->mReadFn(aBuf, aCount, self->mUserData);
   28.50 +}
   28.51 +
   28.52 +//-----------------------------------------------------------------------------
   28.53 +// _ctmStreamWrite() - Write data to a stream.
   28.54 +//-----------------------------------------------------------------------------
   28.55 +CTMuint _ctmStreamWrite(_CTMcontext * self, void * aBuf, CTMuint aCount)
   28.56 +{
   28.57 +  if(!self->mUserData || !self->mWriteFn)
   28.58 +    return 0;
   28.59 +
   28.60 +  return self->mWriteFn(aBuf, aCount, self->mUserData);
   28.61 +}
   28.62 +
   28.63 +//-----------------------------------------------------------------------------
   28.64 +// _ctmStreamReadUINT() - Read an unsigned integer from a stream in a machine
   28.65 +// endian independent manner (for portability).
   28.66 +//-----------------------------------------------------------------------------
   28.67 +CTMuint _ctmStreamReadUINT(_CTMcontext * self)
   28.68 +{
   28.69 +  unsigned char buf[4];
   28.70 +  _ctmStreamRead(self, (void *) buf, 4);
   28.71 +  return ((CTMuint) buf[0]) |
   28.72 +         (((CTMuint) buf[1]) << 8) |
   28.73 +         (((CTMuint) buf[2]) << 16) |
   28.74 +         (((CTMuint) buf[3]) << 24);
   28.75 +}
   28.76 +
   28.77 +//-----------------------------------------------------------------------------
   28.78 +// _ctmStreamWriteUINT() - Write an unsigned integer to a stream in a machine
   28.79 +// endian independent manner (for portability).
   28.80 +//-----------------------------------------------------------------------------
   28.81 +void _ctmStreamWriteUINT(_CTMcontext * self, CTMuint aValue)
   28.82 +{
   28.83 +  unsigned char buf[4];
   28.84 +  buf[0] = aValue & 0x000000ff;
   28.85 +  buf[1] = (aValue >> 8) & 0x000000ff;
   28.86 +  buf[2] = (aValue >> 16) & 0x000000ff;
   28.87 +  buf[3] = (aValue >> 24) & 0x000000ff;
   28.88 +  _ctmStreamWrite(self, (void *) buf, 4);
   28.89 +}
   28.90 +
   28.91 +//-----------------------------------------------------------------------------
   28.92 +// _ctmStreamReadFLOAT() - Read a floating point value from a stream in a
   28.93 +// machine endian independent manner (for portability).
   28.94 +//-----------------------------------------------------------------------------
   28.95 +CTMfloat _ctmStreamReadFLOAT(_CTMcontext * self)
   28.96 +{
   28.97 +  union {
   28.98 +    CTMfloat f;
   28.99 +    CTMuint  i;
  28.100 +  } u;
  28.101 +  u.i = _ctmStreamReadUINT(self);
  28.102 +  return u.f;
  28.103 +}
  28.104 +
  28.105 +//-----------------------------------------------------------------------------
  28.106 +// _ctmStreamWriteFLOAT() - Write a floating point value to a stream in a
  28.107 +// machine endian independent manner (for portability).
  28.108 +//-----------------------------------------------------------------------------
  28.109 +void _ctmStreamWriteFLOAT(_CTMcontext * self, CTMfloat aValue)
  28.110 +{
  28.111 +  union {
  28.112 +    CTMfloat f;
  28.113 +    CTMuint  i;
  28.114 +  } u;
  28.115 +  u.f = aValue;
  28.116 +  _ctmStreamWriteUINT(self, u.i);
  28.117 +}
  28.118 +
  28.119 +//-----------------------------------------------------------------------------
  28.120 +// _ctmStreamReadSTRING() - Read a string value from a stream. The format of
  28.121 +// the string in the stream is: an unsigned integer (string length) followed by
  28.122 +// the string (without null termination).
  28.123 +//-----------------------------------------------------------------------------
  28.124 +void _ctmStreamReadSTRING(_CTMcontext * self, char ** aValue)
  28.125 +{
  28.126 +  CTMuint len;
  28.127 +
  28.128 +  // Clear the old string
  28.129 +  if(*aValue)
  28.130 +  {
  28.131 +    free(*aValue);
  28.132 +    *aValue = (char *) 0;
  28.133 +  }
  28.134 +
  28.135 +  // Get string length
  28.136 +  len = _ctmStreamReadUINT(self);
  28.137 +
  28.138 +  // Read string
  28.139 +  if(len > 0)
  28.140 +  {
  28.141 +    *aValue = (char *) malloc(len + 1);
  28.142 +    if(*aValue)
  28.143 +    {
  28.144 +      _ctmStreamRead(self, (void *) *aValue, len);
  28.145 +      (*aValue)[len] = 0;
  28.146 +    }
  28.147 +  }
  28.148 +}
  28.149 +
  28.150 +//-----------------------------------------------------------------------------
  28.151 +// _ctmStreamWriteSTRING() - Write a string value to a stream. The format of
  28.152 +// the string in the stream is: an unsigned integer (string length) followed by
  28.153 +// the string (without null termination).
  28.154 +//-----------------------------------------------------------------------------
  28.155 +void _ctmStreamWriteSTRING(_CTMcontext * self, const char * aValue)
  28.156 +{
  28.157 +  CTMuint len;
  28.158 +
  28.159 +  // Get string length
  28.160 +  if(aValue)
  28.161 +    len = strlen(aValue);
  28.162 +  else
  28.163 +    len = 0;
  28.164 +
  28.165 +  // Write string length
  28.166 +  _ctmStreamWriteUINT(self, len);
  28.167 +
  28.168 +  // Write string
  28.169 +  if(len > 0)
  28.170 +    _ctmStreamWrite(self, (void *) aValue, len);
  28.171 +}
  28.172 +
  28.173 +//-----------------------------------------------------------------------------
  28.174 +// _ctmStreamReadPackedInts() - Read an compressed binary integer data array
  28.175 +// from a stream, and uncompress it.
  28.176 +//-----------------------------------------------------------------------------
  28.177 +int _ctmStreamReadPackedInts(_CTMcontext * self, CTMint * aData,
  28.178 +  CTMuint aCount, CTMuint aSize, CTMint aSignedInts)
  28.179 +{
  28.180 +  size_t packedSize, unpackedSize;
  28.181 +  CTMuint i, k, x;
  28.182 +  CTMint value;
  28.183 +  unsigned char * packed, * tmp;
  28.184 +  unsigned char props[5];
  28.185 +  int lzmaRes;
  28.186 +
  28.187 +  // Read packed data size from the stream
  28.188 +  packedSize = (size_t) _ctmStreamReadUINT(self);
  28.189 +
  28.190 +  // Read LZMA compression props from the stream
  28.191 +  _ctmStreamRead(self, (void *) props, 5);
  28.192 +
  28.193 +  // Allocate memory and read the packed data from the stream
  28.194 +  packed = (unsigned char *) malloc(packedSize);
  28.195 +  if(!packed)
  28.196 +  {
  28.197 +    self->mError = CTM_OUT_OF_MEMORY;
  28.198 +    return CTM_FALSE;
  28.199 +  }
  28.200 +  _ctmStreamRead(self, (void *) packed, packedSize);
  28.201 +
  28.202 +  // Allocate memory for interleaved array
  28.203 +  tmp = (unsigned char *) malloc(aCount * aSize * 4);
  28.204 +  if(!tmp)
  28.205 +  {
  28.206 +    free(packed);
  28.207 +    self->mError = CTM_OUT_OF_MEMORY;
  28.208 +    return CTM_FALSE;
  28.209 +  }
  28.210 +
  28.211 +  // Uncompress
  28.212 +  unpackedSize = aCount * aSize * 4;
  28.213 +  lzmaRes = LzmaUncompress(tmp, &unpackedSize, packed,
  28.214 +                           &packedSize, props, 5);
  28.215 +
  28.216 +  // Free the packed array
  28.217 +  free(packed);
  28.218 +
  28.219 +  // Error?
  28.220 +  if((lzmaRes != SZ_OK) || (unpackedSize != aCount * aSize * 4))
  28.221 +  {
  28.222 +    self->mError = CTM_LZMA_ERROR;
  28.223 +    free(tmp);
  28.224 +    return CTM_FALSE;
  28.225 +  }
  28.226 +
  28.227 +  // Convert interleaved array to integers
  28.228 +  for(i = 0; i < aCount; ++ i)
  28.229 +  {
  28.230 +    for(k = 0; k < aSize; ++ k)
  28.231 +    {
  28.232 +      value = (CTMint) tmp[i + k * aCount + 3 * aCount * aSize] |
  28.233 +              (((CTMint) tmp[i + k * aCount + 2 * aCount * aSize]) << 8) |
  28.234 +              (((CTMint) tmp[i + k * aCount + aCount * aSize]) << 16) |
  28.235 +              (((CTMint) tmp[i + k * aCount]) << 24);
  28.236 +      // Convert signed magnitude to two's complement?
  28.237 +      if(aSignedInts)
  28.238 +      {
  28.239 +        x = (CTMuint) value;
  28.240 +        value = (x & 1) ? -(CTMint)((x + 1) >> 1) : (CTMint)(x >> 1);
  28.241 +      }
  28.242 +      aData[i * aSize + k] = value;
  28.243 +    }
  28.244 +  }
  28.245 +
  28.246 +  // Free the interleaved array
  28.247 +  free(tmp);
  28.248 +
  28.249 +  return CTM_TRUE;
  28.250 +}
  28.251 +
  28.252 +//-----------------------------------------------------------------------------
  28.253 +// _ctmStreamWritePackedInts() - Compress a binary integer data array, and
  28.254 +// write it to a stream.
  28.255 +//-----------------------------------------------------------------------------
  28.256 +int _ctmStreamWritePackedInts(_CTMcontext * self, CTMint * aData,
  28.257 +  CTMuint aCount, CTMuint aSize, CTMint aSignedInts)
  28.258 +{
  28.259 +  int lzmaRes, lzmaAlgo;
  28.260 +  CTMuint i, k;
  28.261 +  CTMint value;
  28.262 +  size_t bufSize, outPropsSize;
  28.263 +  unsigned char * packed, outProps[5], *tmp;
  28.264 +#ifdef __DEBUG_
  28.265 +  CTMuint negCount = 0;  
  28.266 +#endif
  28.267 +
  28.268 +  // Allocate memory for interleaved array
  28.269 +  tmp = (unsigned char *) malloc(aCount * aSize * 4);
  28.270 +  if(!tmp)
  28.271 +  {
  28.272 +    self->mError = CTM_OUT_OF_MEMORY;
  28.273 +    return CTM_FALSE;
  28.274 +  }
  28.275 +
  28.276 +  // Convert integers to an interleaved array
  28.277 +  for(i = 0; i < aCount; ++ i)
  28.278 +  {
  28.279 +    for(k = 0; k < aSize; ++ k)
  28.280 +    {
  28.281 +      value = aData[i * aSize + k];
  28.282 +      // Convert two's complement to signed magnitude?
  28.283 +      if(aSignedInts)
  28.284 +        value = value < 0 ? -1 - (value << 1) : value << 1;
  28.285 +#ifdef __DEBUG_
  28.286 +      else if(value < 0)
  28.287 +        ++ negCount;
  28.288 +#endif
  28.289 +      tmp[i + k * aCount + 3 * aCount * aSize] = value & 0x000000ff;
  28.290 +      tmp[i + k * aCount + 2 * aCount * aSize] = (value >> 8) & 0x000000ff;
  28.291 +      tmp[i + k * aCount + aCount * aSize] = (value >> 16) & 0x000000ff;
  28.292 +      tmp[i + k * aCount] = (value >> 24) & 0x000000ff;
  28.293 +    }
  28.294 +  }
  28.295 +
  28.296 +  // Allocate memory for the packed data
  28.297 +  bufSize = 1000 + aCount * aSize * 4;
  28.298 +  packed = (unsigned char *) malloc(bufSize);
  28.299 +  if(!packed)
  28.300 +  {
  28.301 +    free(tmp);
  28.302 +    self->mError = CTM_OUT_OF_MEMORY;
  28.303 +    return CTM_FALSE;
  28.304 +  }
  28.305 +
  28.306 +  // Call LZMA to compress
  28.307 +  outPropsSize = 5;
  28.308 +  lzmaAlgo = (self->mCompressionLevel < 1 ? 0 : 1);
  28.309 +  lzmaRes = LzmaCompress(packed,
  28.310 +                         &bufSize,
  28.311 +                         (const unsigned char *) tmp,
  28.312 +                         aCount * aSize * 4,
  28.313 +                         outProps,
  28.314 +                         &outPropsSize,
  28.315 +                         self->mCompressionLevel, // Level (0-9)
  28.316 +                         0, -1, -1, -1, -1, -1,   // Default values (set by level)
  28.317 +                         lzmaAlgo                 // Algorithm (0 = fast, 1 = normal)
  28.318 +                        );
  28.319 +
  28.320 +  // Free temporary array
  28.321 +  free(tmp);
  28.322 +
  28.323 +  // Error?
  28.324 +  if(lzmaRes != SZ_OK)
  28.325 +  {
  28.326 +    self->mError = CTM_LZMA_ERROR;
  28.327 +    free(packed);
  28.328 +    return CTM_FALSE;
  28.329 +  }
  28.330 +
  28.331 +#ifdef __DEBUG_
  28.332 +  printf("%d->%d bytes (%d negative words)\n", aCount * aSize * 4, (int) bufSize, negCount);
  28.333 +#endif
  28.334 +
  28.335 +  // Write packed data size to the stream
  28.336 +  _ctmStreamWriteUINT(self, (CTMuint) bufSize);
  28.337 +
  28.338 +  // Write LZMA compression props to the stream
  28.339 +  _ctmStreamWrite(self, (void *) outProps, 5);
  28.340 +
  28.341 +  // Write the packed data to the stream
  28.342 +  _ctmStreamWrite(self, (void *) packed, (CTMuint) bufSize);
  28.343 +
  28.344 +  // Free the packed data
  28.345 +  free(packed);
  28.346 +
  28.347 +  return CTM_TRUE;
  28.348 +}
  28.349 +
  28.350 +//-----------------------------------------------------------------------------
  28.351 +// _ctmStreamReadPackedFloats() - Read an compressed binary float data array
  28.352 +// from a stream, and uncompress it.
  28.353 +//-----------------------------------------------------------------------------
  28.354 +int _ctmStreamReadPackedFloats(_CTMcontext * self, CTMfloat * aData,
  28.355 +  CTMuint aCount, CTMuint aSize)
  28.356 +{
  28.357 +  CTMuint i, k;
  28.358 +  size_t packedSize, unpackedSize;
  28.359 +  union {
  28.360 +    CTMfloat f;
  28.361 +    CTMint i;
  28.362 +  } value;
  28.363 +  unsigned char * packed, * tmp;
  28.364 +  unsigned char props[5];
  28.365 +  int lzmaRes;
  28.366 +
  28.367 +  // Read packed data size from the stream
  28.368 +  packedSize = (size_t) _ctmStreamReadUINT(self);
  28.369 +
  28.370 +  // Read LZMA compression props from the stream
  28.371 +  _ctmStreamRead(self, (void *) props, 5);
  28.372 +
  28.373 +  // Allocate memory and read the packed data from the stream
  28.374 +  packed = (unsigned char *) malloc(packedSize);
  28.375 +  if(!packed)
  28.376 +  {
  28.377 +    self->mError = CTM_OUT_OF_MEMORY;
  28.378 +    return CTM_FALSE;
  28.379 +  }
  28.380 +  _ctmStreamRead(self, (void *) packed, packedSize);
  28.381 +
  28.382 +  // Allocate memory for interleaved array
  28.383 +  tmp = (unsigned char *) malloc(aCount * aSize * 4);
  28.384 +  if(!tmp)
  28.385 +  {
  28.386 +    free(packed);
  28.387 +    self->mError = CTM_OUT_OF_MEMORY;
  28.388 +    return CTM_FALSE;
  28.389 +  }
  28.390 +
  28.391 +  // Uncompress
  28.392 +  unpackedSize = aCount * aSize * 4;
  28.393 +  lzmaRes = LzmaUncompress(tmp, &unpackedSize, packed,
  28.394 +                           &packedSize, props, 5);
  28.395 +
  28.396 +  // Free the packed array
  28.397 +  free(packed);
  28.398 +
  28.399 +  // Error?
  28.400 +  if((lzmaRes != SZ_OK) || (unpackedSize != aCount * aSize * 4))
  28.401 +  {
  28.402 +    self->mError = CTM_LZMA_ERROR;
  28.403 +    free(tmp);
  28.404 +    return CTM_FALSE;
  28.405 +  }
  28.406 +
  28.407 +  // Convert interleaved array to floats
  28.408 +  for(i = 0; i < aCount; ++ i)
  28.409 +  {
  28.410 +    for(k = 0; k < aSize; ++ k)
  28.411 +    {
  28.412 +      value.i = (CTMint) tmp[i + k * aCount + 3 * aCount * aSize] |
  28.413 +                (((CTMint) tmp[i + k * aCount + 2 * aCount * aSize]) << 8) |
  28.414 +                (((CTMint) tmp[i + k * aCount + aCount * aSize]) << 16) |
  28.415 +                (((CTMint) tmp[i + k * aCount]) << 24);
  28.416 +      aData[i * aSize + k] = value.f;
  28.417 +    }
  28.418 +  }
  28.419 +
  28.420 +  // Free the interleaved array
  28.421 +  free(tmp);
  28.422 +
  28.423 +  return CTM_TRUE;
  28.424 +}
  28.425 +
  28.426 +//-----------------------------------------------------------------------------
  28.427 +// _ctmStreamWritePackedFloats() - Compress a binary float data array, and
  28.428 +// write it to a stream.
  28.429 +//-----------------------------------------------------------------------------
  28.430 +int _ctmStreamWritePackedFloats(_CTMcontext * self, CTMfloat * aData,
  28.431 +  CTMuint aCount, CTMuint aSize)
  28.432 +{
  28.433 +  int lzmaRes, lzmaAlgo;
  28.434 +  CTMuint i, k;
  28.435 +  union {
  28.436 +    CTMfloat f;
  28.437 +    CTMint i;
  28.438 +  } value;
  28.439 +  size_t bufSize, outPropsSize;
  28.440 +  unsigned char * packed, outProps[5], *tmp;
  28.441 +
  28.442 +  // Allocate memory for interleaved array
  28.443 +  tmp = (unsigned char *) malloc(aCount * aSize * 4);
  28.444 +  if(!tmp)
  28.445 +  {
  28.446 +    self->mError = CTM_OUT_OF_MEMORY;
  28.447 +    return CTM_FALSE;
  28.448 +  }
  28.449 +
  28.450 +  // Convert floats to an interleaved array
  28.451 +  for(i = 0; i < aCount; ++ i)
  28.452 +  {
  28.453 +    for(k = 0; k < aSize; ++ k)
  28.454 +    {
  28.455 +      value.f = aData[i * aSize + k];
  28.456 +      tmp[i + k * aCount + 3 * aCount * aSize] = value.i & 0x000000ff;
  28.457 +      tmp[i + k * aCount + 2 * aCount * aSize] = (value.i >> 8) & 0x000000ff;
  28.458 +      tmp[i + k * aCount + aCount * aSize] = (value.i >> 16) & 0x000000ff;
  28.459 +      tmp[i + k * aCount] = (value.i >> 24) & 0x000000ff;
  28.460 +    }
  28.461 +  }
  28.462 +
  28.463 +  // Allocate memory for the packed data
  28.464 +  bufSize = 1000 + aCount * aSize * 4;
  28.465 +  packed = (unsigned char *) malloc(bufSize);
  28.466 +  if(!packed)
  28.467 +  {
  28.468 +    free(tmp);
  28.469 +    self->mError = CTM_OUT_OF_MEMORY;
  28.470 +    return CTM_FALSE;
  28.471 +  }
  28.472 +
  28.473 +  // Call LZMA to compress
  28.474 +  outPropsSize = 5;
  28.475 +  lzmaAlgo = (self->mCompressionLevel < 1 ? 0 : 1);
  28.476 +  lzmaRes = LzmaCompress(packed,
  28.477 +                         &bufSize,
  28.478 +                         (const unsigned char *) tmp,
  28.479 +                         aCount * aSize * 4,
  28.480 +                         outProps,
  28.481 +                         &outPropsSize,
  28.482 +                         self->mCompressionLevel, // Level (0-9)
  28.483 +                         0, -1, -1, -1, -1, -1,   // Default values (set by level)
  28.484 +                         lzmaAlgo                 // Algorithm (0 = fast, 1 = normal)
  28.485 +                        );
  28.486 +
  28.487 +  // Free temporary array
  28.488 +  free(tmp);
  28.489 +
  28.490 +  // Error?
  28.491 +  if(lzmaRes != SZ_OK)
  28.492 +  {
  28.493 +    self->mError = CTM_LZMA_ERROR;
  28.494 +    free(packed);
  28.495 +    return CTM_FALSE;
  28.496 +  }
  28.497 +
  28.498 +#ifdef __DEBUG_
  28.499 +  printf("%d->%d bytes\n", aCount * aSize * 4, (int) bufSize);
  28.500 +#endif
  28.501 +
  28.502 +  // Write packed data size to the stream
  28.503 +  _ctmStreamWriteUINT(self, (CTMuint) bufSize);
  28.504 +
  28.505 +  // Write LZMA compression props to the stream
  28.506 +  _ctmStreamWrite(self, (void *) outProps, 5);
  28.507 +
  28.508 +  // Write the packed data to the stream
  28.509 +  _ctmStreamWrite(self, (void *) packed, (CTMuint) bufSize);
  28.510 +
  28.511 +  // Free the packed data
  28.512 +  free(packed);
  28.513 +
  28.514 +  return CTM_TRUE;
  28.515 +}
    29.1 --- a/src/chunk.h	Tue Sep 10 15:29:45 2013 +0300
    29.2 +++ b/src/chunk.h	Thu Sep 26 04:47:05 2013 +0300
    29.3 @@ -18,33 +18,28 @@
    29.4  	// --- first level chunks ---
    29.5  	// children of CNK_SCENE
    29.6  	CNK_ENV,			// environmental parameters
    29.7 -	CNK_MTL_LIST,		// material library
    29.8 -	CNK_MESH_LIST,		// all the meshes hang under this chunk
    29.9 -	CNK_LIGHT_LIST,		// likewise for lights
   29.10 -	CNK_CAMERA_LIST,	// likewise for cameras
   29.11 -	CNK_NODE_LIST,		// likewise for nodes
   29.12 +	CNK_MTL,			// material
   29.13 +	CNK_MESH,
   29.14 +	CNK_LIGHT,
   29.15 +	CNK_CAMERA,
   29.16 +	CNK_NODE,
   29.17  
   29.18  	// --- second level chunks ---
   29.19  	// children of CNK_ENV
   29.20  	CNK_ENV_AMBIENT,	// ambient color, contains a single CNK_FLOAT3
   29.21  	CNK_ENV_FOG,
   29.22  
   29.23 -	// children of CNK_*_LIST
   29.24 -	CNK_MTL,
   29.25 -	CNK_MESH,
   29.26 -	CNK_LIGHT,
   29.27 -	CNK_CAMERA,
   29.28 -	CNK_NODE,
   29.29 -
   29.30  	// --- third level chunks ---
   29.31  	// children of CNK_FOG
   29.32  	CNK_FOG_COLOR,		// fog color, contains a single CNK_FLOAT3
   29.33 -	CNK_FOG_EXP,		// fog exponent, contains a single CNK_REAL
   29.34 +	CNK_FOG_EXP,		// fog exponent, contains a single CNK_FLOAT
   29.35  
   29.36  	// children of CNK_MTL
   29.37 +	CNK_MTL_NAME,		// has a single CNK_STRING
   29.38  	CNK_MTL_ATTR,		// material attribute, has a CNK_STRING for its name,
   29.39  						// a CNK_MTL_ATTR_VAL, and optionally a CNK_MTL_ATTR_MAP
   29.40  	// children of CNK_MTL_ATTR
   29.41 +	CNK_MTL_ATTR_NAME,	// has a single CNK_STRING
   29.42  	CNK_MTL_ATTR_VAL,	// can have a single CNK_FLOAT, CNK_FLOAT3, or CNK_FLOAT4
   29.43  	CNK_MTL_ATTR_MAP,	// has a single CNK_STRING
   29.44  
   29.45 @@ -60,6 +55,7 @@
   29.46  	CNK_MESH_COLOR_LIST,	// has a series of CNK_FLOAT4 chunks
   29.47  	CNK_MESH_BONES_LIST,	// has a series of CNK_INT or CNK_STRING chunks identifying the bone nodes
   29.48  	CNK_MESH_FACE_LIST,		// has a series of CNK_FACE chunks
   29.49 +	CNK_MESH_FILE,			// optionally mesh data may be in another file, has a CNK_STRING filename
   29.50  
   29.51  	// child of CNK_MESH_FACE_LIST
   29.52  	CNK_MESH_FACE,			// has three CNK_INT chunks
   29.53 @@ -90,14 +86,14 @@
   29.54  	CNK_NODE_LIGHT,			// same as CNK_NODE_MESH
   29.55  	CNK_NODE_CAMERA,		// same as CNK_NODE_MESH
   29.56  
   29.57 -	CNK_NODE_POS,			// has a CNK_VEC3, position vector
   29.58 -	CNK_NODE_ROT,			// has a CNK_VEC4, rotation quaternion (x, y, z imaginary, w real)
   29.59 -	CNK_NODE_SCALE,			// has a CNK_VEC3, scaling
   29.60 -	CNK_NODE_PIVOT,			// has a CNK_VEC3, pivot point
   29.61 +	CNK_NODE_POS,			// has a CNK_FLOAT3, position vector
   29.62 +	CNK_NODE_ROT,			// has a CNK_FLOAT4, rotation quaternion (x, y, z imaginary, w real)
   29.63 +	CNK_NODE_SCALE,			// has a CNK_FLOAT3, scaling
   29.64 +	CNK_NODE_PIVOT,			// has a CNK_FLOAT3, pivot point
   29.65  
   29.66 -	CNK_NODE_MATRIX0,		// has a CNK_VEC4, first matrix row (4x3)
   29.67 -	CNK_NODE_MATRXI1,		// has a CNK_VEC4, second matrix row (4x3)
   29.68 -	CNK_NODE_MATRIX2,		// has a CNK_VEC4, third matrix row (4x3)
   29.69 +	CNK_NODE_MATRIX0,		// has a CNK_FLOAT4, first matrix row (4x3)
   29.70 +	CNK_NODE_MATRXI1,		// has a CNK_FLOAT4, second matrix row (4x3)
   29.71 +	CNK_NODE_MATRIX2,		// has a CNK_FLOAT4, third matrix row (4x3)
   29.72  
   29.73  	MAX_NUM_CHUNKS
   29.74  };
    30.1 --- a/src/goat3d.cc	Tue Sep 10 15:29:45 2013 +0300
    30.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.3 @@ -1,409 +0,0 @@
    30.4 -#include "goat3d.h"
    30.5 -#include "goat3d_impl.h"
    30.6 -#include "chunk.h"
    30.7 -
    30.8 -Scene::Scene()
    30.9 -	: name("unnamed"), ambient(0.05, 0.05, 0.05)
   30.10 -{
   30.11 -}
   30.12 -
   30.13 -Scene::~Scene()
   30.14 -{
   30.15 -	clear();
   30.16 -}
   30.17 -
   30.18 -void Scene::clear()
   30.19 -{
   30.20 -	for(size_t i=0; i<materials.size(); i++) {
   30.21 -		delete materials[i];
   30.22 -	}
   30.23 -	materials.clear();
   30.24 -
   30.25 -	for(size_t i=0; i<meshes.size(); i++) {
   30.26 -		delete meshes[i];
   30.27 -	}
   30.28 -	meshes.clear();
   30.29 -
   30.30 -	for(size_t i=0; i<lights.size(); i++) {
   30.31 -		delete lights[i];
   30.32 -	}
   30.33 -	lights.clear();
   30.34 -
   30.35 -	for(size_t i=0; i<cameras.size(); i++) {
   30.36 -		delete cameras[i];
   30.37 -	}
   30.38 -	cameras.clear();
   30.39 -
   30.40 -	for(size_t i=0; i<nodes.size(); i++) {
   30.41 -		delete_node_tree(nodes[i]);
   30.42 -	}
   30.43 -	nodes.clear();
   30.44 -
   30.45 -	name = "unnamed";
   30.46 -}
   30.47 -
   30.48 -void Scene::set_name(const char *name)
   30.49 -{
   30.50 -	this->name = name;
   30.51 -}
   30.52 -
   30.53 -const char *Scene::get_name() const
   30.54 -{
   30.55 -	return name.c_str();
   30.56 -}
   30.57 -
   30.58 -void Scene::set_ambient(const Vector3 &amb)
   30.59 -{
   30.60 -	ambient = amb;
   30.61 -}
   30.62 -
   30.63 -const Vector3 &Scene::get_ambient() const
   30.64 -{
   30.65 -	return ambient;
   30.66 -}
   30.67 -
   30.68 -void Scene::add_material(Material *mat)
   30.69 -{
   30.70 -	materials.push_back(mat);
   30.71 -}
   30.72 -
   30.73 -Material *Scene::get_material(int idx) const
   30.74 -{
   30.75 -	return idx >=0 && idx < (int)materials.size() ? materials[idx] : 0;
   30.76 -}
   30.77 -
   30.78 -Material *Scene::get_material(const char *name) const
   30.79 -{
   30.80 -	for(size_t i=0; i<materials.size(); i++) {
   30.81 -		if(materials[i]->name == std::string(name)) {
   30.82 -			return materials[i];
   30.83 -		}
   30.84 -	}
   30.85 -	return 0;
   30.86 -}
   30.87 -
   30.88 -int Scene::get_material_count() const
   30.89 -{
   30.90 -	return (int)materials.size();
   30.91 -}
   30.92 -
   30.93 -
   30.94 -void Scene::add_mesh(Mesh *mesh)
   30.95 -{
   30.96 -	meshes.push_back(mesh);
   30.97 -}
   30.98 -
   30.99 -Mesh *Scene::get_mesh(int idx) const
  30.100 -{
  30.101 -	return idx >= 0 && idx < (int)meshes.size() ? meshes[idx] : 0;
  30.102 -}
  30.103 -
  30.104 -Mesh *Scene::get_mesh(const char *name) const
  30.105 -{
  30.106 -	for(size_t i=0; i<meshes.size(); i++) {
  30.107 -		if(meshes[i]->name == std::string(name)) {
  30.108 -			return meshes[i];
  30.109 -		}
  30.110 -	}
  30.111 -	return 0;
  30.112 -}
  30.113 -
  30.114 -int Scene::get_mesh_count() const
  30.115 -{
  30.116 -	return (int)meshes.size();
  30.117 -}
  30.118 -
  30.119 -
  30.120 -void Scene::add_light(Light *light)
  30.121 -{
  30.122 -	lights.push_back(light);
  30.123 -}
  30.124 -
  30.125 -Light *Scene::get_light(int idx) const
  30.126 -{
  30.127 -	return idx >= 0 && idx < (int)lights.size() ? lights[idx] : 0;
  30.128 -}
  30.129 -
  30.130 -Light *Scene::get_light(const char *name) const
  30.131 -{
  30.132 -	for(size_t i=0; i<lights.size(); i++) {
  30.133 -		if(lights[i]->name == std::string(name)) {
  30.134 -			return lights[i];
  30.135 -		}
  30.136 -	}
  30.137 -	return 0;
  30.138 -}
  30.139 -
  30.140 -int Scene::get_light_count() const
  30.141 -{
  30.142 -	return (int)lights.size();
  30.143 -}
  30.144 -
  30.145 -
  30.146 -void Scene::add_camera(Camera *cam)
  30.147 -{
  30.148 -	cameras.push_back(cam);
  30.149 -}
  30.150 -
  30.151 -Camera *Scene::get_camera(int idx) const
  30.152 -{
  30.153 -	return idx >= 0 && idx < (int)cameras.size() ? cameras[idx] : 0;
  30.154 -}
  30.155 -
  30.156 -Camera *Scene::get_camera(const char *name) const
  30.157 -{
  30.158 -	for(size_t i=0; i<cameras.size(); i++) {
  30.159 -		if(cameras[i]->name == std::string(name)) {
  30.160 -			return cameras[i];
  30.161 -		}
  30.162 -	}
  30.163 -	return 0;
  30.164 -}
  30.165 -
  30.166 -int Scene::get_camera_count() const
  30.167 -{
  30.168 -	return (int)cameras.size();
  30.169 -}
  30.170 -
  30.171 -
  30.172 -void Scene::add_node(Node *node)
  30.173 -{
  30.174 -	nodes.push_back(node);
  30.175 -}
  30.176 -
  30.177 -Node *Scene::get_node(int idx) const
  30.178 -{
  30.179 -	return idx >= 0 && idx < (int)nodes.size() ? nodes[idx] : 0;
  30.180 -}
  30.181 -
  30.182 -Node *Scene::get_node(const char *name) const
  30.183 -{
  30.184 -	for(size_t i=0; i<nodes.size(); i++) {
  30.185 -		if(strcmp(nodes[i]->get_name(), name) == 0) {
  30.186 -			return nodes[i];
  30.187 -		}
  30.188 -	}
  30.189 -	return 0;
  30.190 -}
  30.191 -
  30.192 -int Scene::get_node_count() const
  30.193 -{
  30.194 -	return (int)nodes.size();
  30.195 -}
  30.196 -
  30.197 -
  30.198 -bool Scene::load(goat3d_io *io)
  30.199 -{
  30.200 -	return false;
  30.201 -}
  30.202 -
  30.203 -static long save_env(const Scene *scn, long offset, goat3d_io *io);
  30.204 -static long save_materials(const Scene *scn, long offset, goat3d_io *io);
  30.205 -static long save_material(const Material *mat, long offset, goat3d_io *io);
  30.206 -static long save_mat_attrib(const char *name, const MaterialAttrib &attr, long offset, goat3d_io *io);
  30.207 -static long save_meshes(const Scene *scn, long offset, goat3d_io *io);
  30.208 -static long save_lights(const Scene *scn, long offset, goat3d_io *io);
  30.209 -static long save_cameras(const Scene *scn, long offset, goat3d_io *io);
  30.210 -static long save_nodes(const Scene *scn, long offset, goat3d_io *io);
  30.211 -
  30.212 -static long write_chunk_float(int id, float val, long offs, goat3d_io *io);
  30.213 -static long write_chunk_float3(int id, const Vector3 &vec, long offs, goat3d_io *io);
  30.214 -static long write_chunk_float4(int id, const Vector4 &vec, long offs, goat3d_io *io);
  30.215 -
  30.216 -bool Scene::save(goat3d_io *io) const
  30.217 -{
  30.218 -	long res;
  30.219 -
  30.220 -	ChunkHeader hdr;
  30.221 -	hdr.id = CNK_SCENE;
  30.222 -	hdr.size = sizeof hdr;
  30.223 -
  30.224 -	if((res = save_env(this, hdr.size, io)) < 0) {
  30.225 -		return false;
  30.226 -	}
  30.227 -	hdr.size += res;
  30.228 -
  30.229 -	if((res = save_materials(this, hdr.size, io)) < 0) {
  30.230 -		return false;
  30.231 -	}
  30.232 -	hdr.size += res;
  30.233 -
  30.234 -	if((res = save_meshes(this, hdr.size, io)) < 0) {
  30.235 -		return false;
  30.236 -	}
  30.237 -	hdr.size += res;
  30.238 -
  30.239 -	if((res = save_lights(this, hdr.size, io)) < 0) {
  30.240 -		return false;
  30.241 -	}
  30.242 -	hdr.size += res;
  30.243 -
  30.244 -	if((res = save_cameras(this, hdr.size, io)) < 0) {
  30.245 -		return false;
  30.246 -	}
  30.247 -	hdr.size += res;
  30.248 -
  30.249 -	if((res = save_nodes(this, hdr.size, io)) < 0) {
  30.250 -		return false;
  30.251 -	}
  30.252 -	hdr.size += res;
  30.253 -
  30.254 -	// now go back and write the root chunk
  30.255 -	io->seek(0, SEEK_SET, io->cls);
  30.256 -	if(io->write(&hdr, sizeof hdr, io->cls) < (ssize_t)sizeof hdr) {
  30.257 -		return false;
  30.258 -	}
  30.259 -
  30.260 -	return true;
  30.261 -}
  30.262 -
  30.263 -
  30.264 -static long save_env(const Scene *scn, long offset, goat3d_io *io)
  30.265 -{
  30.266 -	long res;
  30.267 -
  30.268 -	ChunkHeader hdr;
  30.269 -	hdr.id = CNK_ENV;
  30.270 -	hdr.size = sizeof hdr;
  30.271 -
  30.272 -	if((res = write_chunk_float3(CNK_ENV_AMBIENT, scn->get_ambient(), offset, io)) < 0) {
  30.273 -		return -1;
  30.274 -	}
  30.275 -	hdr.size += res;
  30.276 -
  30.277 -	// TODO add fog chunk
  30.278 -
  30.279 -	io->seek(offset, SEEK_SET, io->cls);
  30.280 -	if(io->write(&hdr, sizeof hdr, io->cls) < (ssize_t)sizeof hdr) {
  30.281 -		return -1;
  30.282 -	}
  30.283 -	return hdr.size;
  30.284 -}
  30.285 -
  30.286 -static long save_materials(const Scene *scn, long offset, goat3d_io *io)
  30.287 -{
  30.288 -	long res;
  30.289 -
  30.290 -	ChunkHeader hdr;
  30.291 -	hdr.id = CNK_MTL_LIST;
  30.292 -	hdr.size = sizeof hdr;
  30.293 -
  30.294 -	for(int i=0; i<scn->get_material_count(); i++) {
  30.295 -		if((res = save_material(scn->get_material(i), offset + hdr.size, io)) < 0) {
  30.296 -			return -1;
  30.297 -		}
  30.298 -		hdr.size += res;
  30.299 -	}
  30.300 -
  30.301 -	io->seek(offset, SEEK_SET, io->cls);
  30.302 -	if(io->write(&hdr, hdr.size, io->cls) < hdr.size) {
  30.303 -		return -1;
  30.304 -	}
  30.305 -	return hdr.size;
  30.306 -}
  30.307 -
  30.308 -static long save_material(const Material *mat, long offset, goat3d_io *io)
  30.309 -{
  30.310 -	long res;
  30.311 -
  30.312 -	ChunkHeader hdr;
  30.313 -	hdr.id = CNK_MTL;
  30.314 -	hdr.size = sizeof hdr;
  30.315 -
  30.316 -	for(int i=0; i<mat->get_attrib_count(); i++) {
  30.317 -		const char *name = mat->get_attrib_name(i);
  30.318 -		if((res = save_mat_attrib(name, (*mat)[i], offset + hdr.size, io)) < 0) {
  30.319 -			return -1;
  30.320 -		}
  30.321 -		hdr.size += res;
  30.322 -	}
  30.323 -
  30.324 -	io->seek(offset, SEEK_SET, io->cls);
  30.325 -	if(io->write(&hdr, hdr.size, io->cls) < hdr.size) {
  30.326 -		return -1;
  30.327 -	}
  30.328 -	return hdr.size;
  30.329 -}
  30.330 -
  30.331 -static long save_mat_attrib(const char *name, const MaterialAttrib &attr, long offset, goat3d_io *io)
  30.332 -{
  30.333 -	long res;
  30.334 -
  30.335 -	ChunkHeader hdr;
  30.336 -	hdr.id = CNK_MTL_ATTR;
  30.337 -	hdr.size = sizeof hdr;
  30.338 -
  30.339 -	// TODO cont.
  30.340 -	return -1;
  30.341 -}
  30.342 -
  30.343 -static long save_meshes(const Scene *scn, long offset, goat3d_io *io)
  30.344 -{
  30.345 -	return 0;
  30.346 -}
  30.347 -
  30.348 -static long save_lights(const Scene *scn, long offset, goat3d_io *io)
  30.349 -{
  30.350 -	return 0;
  30.351 -}
  30.352 -
  30.353 -static long save_cameras(const Scene *scn, long offset, goat3d_io *io)
  30.354 -{
  30.355 -	return 0;
  30.356 -}
  30.357 -
  30.358 -static long save_nodes(const Scene *scn, long offset, goat3d_io *io)
  30.359 -{
  30.360 -	return 0;
  30.361 -}
  30.362 -
  30.363 -static long write_chunk_float(int id, float val, long offs, goat3d_io *io)
  30.364 -{
  30.365 -	int size = sizeof(ChunkHeader) + sizeof val;
  30.366 -	char *buf = (char*)alloca(size);
  30.367 -
  30.368 -	Chunk *c = (Chunk*)buf;
  30.369 -	c->hdr.id = id;
  30.370 -	c->hdr.size = size;
  30.371 -	*(float*)c->data = val;
  30.372 -
  30.373 -	io->seek(offs, SEEK_SET, io->cls);
  30.374 -	if(io->write(buf, size, io->cls) < size) {
  30.375 -		return -1;
  30.376 -	}
  30.377 -	return size;
  30.378 -}
  30.379 -
  30.380 -static long write_chunk_float3(int id, const Vector3 &vec, long offs, goat3d_io *io)
  30.381 -{
  30.382 -	int size = sizeof(ChunkHeader) + sizeof vec;
  30.383 -	char *buf = (char*)alloca(size);
  30.384 -
  30.385 -	Chunk *c = (Chunk*)buf;
  30.386 -	c->hdr.id = id;
  30.387 -	c->hdr.size = size;
  30.388 -	*(Vector3*)c->data = vec;
  30.389 -
  30.390 -	io->seek(offs, SEEK_SET, io->cls);
  30.391 -	if(io->write(buf, size, io->cls) < size) {
  30.392 -		return -1;
  30.393 -	}
  30.394 -	return size;
  30.395 -}
  30.396 -
  30.397 -static long write_chunk_float4(int id, const Vector4 &vec, long offs, goat3d_io *io)
  30.398 -{
  30.399 -	int size = sizeof(ChunkHeader) + sizeof vec;
  30.400 -	char *buf = (char*)alloca(size);
  30.401 -
  30.402 -	Chunk *c = (Chunk*)buf;
  30.403 -	c->hdr.id = id;
  30.404 -	c->hdr.size = size;
  30.405 -	*(Vector4*)c->data = vec;
  30.406 -
  30.407 -	io->seek(offs, SEEK_SET, io->cls);
  30.408 -	if(io->write(buf, size, io->cls) < size) {
  30.409 -		return -1;
  30.410 -	}
  30.411 -	return size;
  30.412 -}
    31.1 --- a/src/goat3d_impl.h	Tue Sep 10 15:29:45 2013 +0300
    31.2 +++ b/src/goat3d_impl.h	Thu Sep 26 04:47:05 2013 +0300
    31.3 @@ -60,7 +60,12 @@
    31.4  
    31.5  	bool load(goat3d_io *io);
    31.6  	bool save(goat3d_io *io) const;
    31.7 +
    31.8 +	bool loadxml(goat3d_io *io);
    31.9 +	bool savexml(goat3d_io *io) const;
   31.10  };
   31.11  
   31.12 +void io_fprintf(goat3d_io *io, const char *fmt, ...);
   31.13 +void io_vfprintf(goat3d_io *io, const char *fmt, va_list ap);
   31.14  
   31.15  #endif	// GOAT3D_IMPL_H_
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/src/goat3d_scene.cc	Thu Sep 26 04:47:05 2013 +0300
    32.3 @@ -0,0 +1,253 @@
    32.4 +#include <stdarg.h>
    32.5 +#include "goat3d.h"
    32.6 +#include "goat3d_impl.h"
    32.7 +#include "chunk.h"
    32.8 +
    32.9 +Scene::Scene()
   32.10 +	: name("unnamed"), ambient(0.05, 0.05, 0.05)
   32.11 +{
   32.12 +}
   32.13 +
   32.14 +Scene::~Scene()
   32.15 +{
   32.16 +	clear();
   32.17 +}
   32.18 +
   32.19 +void Scene::clear()
   32.20 +{
   32.21 +	for(size_t i=0; i<materials.size(); i++) {
   32.22 +		delete materials[i];
   32.23 +	}
   32.24 +	materials.clear();
   32.25 +
   32.26 +	for(size_t i=0; i<meshes.size(); i++) {
   32.27 +		delete meshes[i];
   32.28 +	}
   32.29 +	meshes.clear();
   32.30 +
   32.31 +	for(size_t i=0; i<lights.size(); i++) {
   32.32 +		delete lights[i];
   32.33 +	}
   32.34 +	lights.clear();
   32.35 +
   32.36 +	for(size_t i=0; i<cameras.size(); i++) {
   32.37 +		delete cameras[i];
   32.38 +	}
   32.39 +	cameras.clear();
   32.40 +
   32.41 +	for(size_t i=0; i<nodes.size(); i++) {
   32.42 +		delete_node_tree(nodes[i]);
   32.43 +	}
   32.44 +	nodes.clear();
   32.45 +
   32.46 +	name = "unnamed";
   32.47 +}
   32.48 +
   32.49 +void Scene::set_name(const char *name)
   32.50 +{
   32.51 +	this->name = name;
   32.52 +}
   32.53 +
   32.54 +const char *Scene::get_name() const
   32.55 +{
   32.56 +	return name.c_str();
   32.57 +}
   32.58 +
   32.59 +void Scene::set_ambient(const Vector3 &amb)
   32.60 +{
   32.61 +	ambient = amb;
   32.62 +}
   32.63 +
   32.64 +const Vector3 &Scene::get_ambient() const
   32.65 +{
   32.66 +	return ambient;
   32.67 +}
   32.68 +
   32.69 +void Scene::add_material(Material *mat)
   32.70 +{
   32.71 +	materials.push_back(mat);
   32.72 +}
   32.73 +
   32.74 +Material *Scene::get_material(int idx) const
   32.75 +{
   32.76 +	return idx >=0 && idx < (int)materials.size() ? materials[idx] : 0;
   32.77 +}
   32.78 +
   32.79 +Material *Scene::get_material(const char *name) const
   32.80 +{
   32.81 +	for(size_t i=0; i<materials.size(); i++) {
   32.82 +		if(materials[i]->name == std::string(name)) {
   32.83 +			return materials[i];
   32.84 +		}
   32.85 +	}
   32.86 +	return 0;
   32.87 +}
   32.88 +
   32.89 +int Scene::get_material_count() const
   32.90 +{
   32.91 +	return (int)materials.size();
   32.92 +}
   32.93 +
   32.94 +
   32.95 +void Scene::add_mesh(Mesh *mesh)
   32.96 +{
   32.97 +	meshes.push_back(mesh);
   32.98 +}
   32.99 +
  32.100 +Mesh *Scene::get_mesh(int idx) const
  32.101 +{
  32.102 +	return idx >= 0 && idx < (int)meshes.size() ? meshes[idx] : 0;
  32.103 +}
  32.104 +
  32.105 +Mesh *Scene::get_mesh(const char *name) const
  32.106 +{
  32.107 +	for(size_t i=0; i<meshes.size(); i++) {
  32.108 +		if(meshes[i]->name == std::string(name)) {
  32.109 +			return meshes[i];
  32.110 +		}
  32.111 +	}
  32.112 +	return 0;
  32.113 +}
  32.114 +
  32.115 +int Scene::get_mesh_count() const
  32.116 +{
  32.117 +	return (int)meshes.size();
  32.118 +}
  32.119 +
  32.120 +
  32.121 +void Scene::add_light(Light *light)
  32.122 +{
  32.123 +	lights.push_back(light);
  32.124 +}
  32.125 +
  32.126 +Light *Scene::get_light(int idx) const
  32.127 +{
  32.128 +	return idx >= 0 && idx < (int)lights.size() ? lights[idx] : 0;
  32.129 +}
  32.130 +
  32.131 +Light *Scene::get_light(const char *name) const
  32.132 +{
  32.133 +	for(size_t i=0; i<lights.size(); i++) {
  32.134 +		if(lights[i]->name == std::string(name)) {
  32.135 +			return lights[i];
  32.136 +		}
  32.137 +	}
  32.138 +	return 0;
  32.139 +}
  32.140 +
  32.141 +int Scene::get_light_count() const
  32.142 +{
  32.143 +	return (int)lights.size();
  32.144 +}
  32.145 +
  32.146 +
  32.147 +void Scene::add_camera(Camera *cam)
  32.148 +{
  32.149 +	cameras.push_back(cam);
  32.150 +}
  32.151 +
  32.152 +Camera *Scene::get_camera(int idx) const
  32.153 +{
  32.154 +	return idx >= 0 && idx < (int)cameras.size() ? cameras[idx] : 0;
  32.155 +}
  32.156 +
  32.157 +Camera *Scene::get_camera(const char *name) const
  32.158 +{
  32.159 +	for(size_t i=0; i<cameras.size(); i++) {
  32.160 +		if(cameras[i]->name == std::string(name)) {
  32.161 +			return cameras[i];
  32.162 +		}
  32.163 +	}
  32.164 +	return 0;
  32.165 +}
  32.166 +
  32.167 +int Scene::get_camera_count() const
  32.168 +{
  32.169 +	return (int)cameras.size();
  32.170 +}
  32.171 +
  32.172 +
  32.173 +void Scene::add_node(Node *node)
  32.174 +{
  32.175 +	nodes.push_back(node);
  32.176 +}
  32.177 +
  32.178 +Node *Scene::get_node(int idx) const
  32.179 +{
  32.180 +	return idx >= 0 && idx < (int)nodes.size() ? nodes[idx] : 0;
  32.181 +}
  32.182 +
  32.183 +Node *Scene::get_node(const char *name) const
  32.184 +{
  32.185 +	for(size_t i=0; i<nodes.size(); i++) {
  32.186 +		if(strcmp(nodes[i]->get_name(), name) == 0) {
  32.187 +			return nodes[i];
  32.188 +		}
  32.189 +	}
  32.190 +	return 0;
  32.191 +}
  32.192 +
  32.193 +int Scene::get_node_count() const
  32.194 +{
  32.195 +	return (int)nodes.size();
  32.196 +}
  32.197 +
  32.198 +
  32.199 +bool Scene::load(goat3d_io *io)
  32.200 +{
  32.201 +	return false;
  32.202 +}
  32.203 +
  32.204 +// Scene::save is defined in goat3d_write.cc
  32.205 +
  32.206 +
  32.207 +void io_fprintf(goat3d_io *io, const char *fmt, ...)
  32.208 +{
  32.209 +	va_list ap;
  32.210 +
  32.211 +	va_start(ap, fmt);
  32.212 +	io_vfprintf(io, fmt, ap);
  32.213 +	va_end(ap);
  32.214 +}
  32.215 +
  32.216 +
  32.217 +void io_vfprintf(goat3d_io *io, const char *fmt, va_list ap)
  32.218 +{
  32.219 +	char smallbuf[256];
  32.220 +	char *buf = smallbuf;
  32.221 +	int sz = sizeof smallbuf;
  32.222 +
  32.223 +	int retsz = vsnprintf(buf, sz - 1, fmt, ap);
  32.224 +
  32.225 +	if(retsz >= sz) {
  32.226 +		/* C99 mandates that snprintf with a short count should return the
  32.227 +		 * number of characters that *would* be printed.
  32.228 +		 */
  32.229 +		buf = new char[retsz + 1];
  32.230 +
  32.231 +		vsnprintf(buf, retsz, fmt, ap);
  32.232 +
  32.233 +	} else if(retsz <= 0) {
  32.234 +		/* SUSv2 and microsoft specify that snprintf with a short count
  32.235 +		 * returns an arbitrary value <= 0. So let's try allocating
  32.236 +		 * bigger and bigger arrays until we find the correct size.
  32.237 +		 */
  32.238 +		sz = sizeof smallbuf;
  32.239 +		do {
  32.240 +			sz *= 2;
  32.241 +			if(buf != smallbuf) {
  32.242 +				delete [] buf;
  32.243 +			}
  32.244 +			buf = new char[sz + 1];
  32.245 +
  32.246 +			retsz = vsnprintf(buf, sz, fmt, ap);
  32.247 +		} while(retsz <= 0);
  32.248 +	}
  32.249 +
  32.250 +	io->write(buf, sz, io->cls);
  32.251 +
  32.252 +	if(buf != smallbuf) {
  32.253 +		delete [] buf;
  32.254 +	}
  32.255 +
  32.256 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/src/goat3d_write.cc	Thu Sep 26 04:47:05 2013 +0300
    33.3 @@ -0,0 +1,220 @@
    33.4 +#include "goat3d_impl.h"
    33.5 +#include "chunk.h"
    33.6 +
    33.7 +/*
    33.8 +static long save_env(const Scene *scn, long offset, goat3d_io *io);
    33.9 +static long save_materials(const Scene *scn, long offset, goat3d_io *io);
   33.10 +static long save_material(const Material *mat, long offset, goat3d_io *io);
   33.11 +static long save_mat_attrib(const char *name, const MaterialAttrib &attr, long offset, goat3d_io *io);
   33.12 +static long save_meshes(const Scene *scn, long offset, goat3d_io *io);
   33.13 +static long save_lights(const Scene *scn, long offset, goat3d_io *io);
   33.14 +static long save_cameras(const Scene *scn, long offset, goat3d_io *io);
   33.15 +static long save_nodes(const Scene *scn, long offset, goat3d_io *io);
   33.16 +
   33.17 +static long write_chunk_float(int id, float val, long offs, goat3d_io *io);
   33.18 +static long write_chunk_float3(int id, const Vector3 &vec, long offs, goat3d_io *io);
   33.19 +static long write_chunk_float4(int id, const Vector4 &vec, long offs, goat3d_io *io);
   33.20 +*/
   33.21 +
   33.22 +bool Scene::save(goat3d_io *io) const
   33.23 +{
   33.24 +	/*
   33.25 +	long res;
   33.26 +
   33.27 +	ChunkHeader hdr;
   33.28 +	hdr.id = CNK_SCENE;
   33.29 +	hdr.size = sizeof hdr;
   33.30 +
   33.31 +	if((res = save_env(this, hdr.size, io)) < 0) {
   33.32 +		return false;
   33.33 +	}
   33.34 +	hdr.size += res;
   33.35 +
   33.36 +	if((res = save_materials(this, hdr.size, io)) < 0) {
   33.37 +		return false;
   33.38 +	}
   33.39 +	hdr.size += res;
   33.40 +
   33.41 +	if((res = save_meshes(this, hdr.size, io)) < 0) {
   33.42 +		return false;
   33.43 +	}
   33.44 +	hdr.size += res;
   33.45 +
   33.46 +	if((res = save_lights(this, hdr.size, io)) < 0) {
   33.47 +		return false;
   33.48 +	}
   33.49 +	hdr.size += res;
   33.50 +
   33.51 +	if((res = save_cameras(this, hdr.size, io)) < 0) {
   33.52 +		return false;
   33.53 +	}
   33.54 +	hdr.size += res;
   33.55 +
   33.56 +	if((res = save_nodes(this, hdr.size, io)) < 0) {
   33.57 +		return false;
   33.58 +	}
   33.59 +	hdr.size += res;
   33.60 +
   33.61 +	// now go back and write the root chunk
   33.62 +	io->seek(0, SEEK_SET, io->cls);
   33.63 +	if(io->write(&hdr, sizeof hdr, io->cls) < (ssize_t)sizeof hdr) {
   33.64 +		return false;
   33.65 +	}
   33.66 +
   33.67 +	return true;
   33.68 +	*/
   33.69 +	return false;
   33.70 +}
   33.71 +
   33.72 +
   33.73 +#if 0
   33.74 +static long save_env(const Scene *scn, long offset, goat3d_io *io)
   33.75 +{
   33.76 +	long res;
   33.77 +
   33.78 +	ChunkHeader hdr;
   33.79 +	hdr.id = CNK_ENV;
   33.80 +	hdr.size = sizeof hdr;
   33.81 +
   33.82 +	if((res = write_chunk_float3(CNK_ENV_AMBIENT, scn->get_ambient(), offset, io)) < 0) {
   33.83 +		return -1;
   33.84 +	}
   33.85 +	hdr.size += res;
   33.86 +
   33.87 +	// TODO add fog chunk
   33.88 +
   33.89 +	io->seek(offset, SEEK_SET, io->cls);
   33.90 +	if(io->write(&hdr, sizeof hdr, io->cls) < (ssize_t)sizeof hdr) {
   33.91 +		return -1;
   33.92 +	}
   33.93 +	return hdr.size;
   33.94 +}
   33.95 +
   33.96 +static long save_materials(const Scene *scn, long offset, goat3d_io *io)
   33.97 +{
   33.98 +	long res;
   33.99 +
  33.100 +	ChunkHeader hdr;
  33.101 +	hdr.id = CNK_MTL_LIST;
  33.102 +	hdr.size = sizeof hdr;
  33.103 +
  33.104 +	for(int i=0; i<scn->get_material_count(); i++) {
  33.105 +		if((res = save_material(scn->get_material(i), offset + hdr.size, io)) < 0) {
  33.106 +			return -1;
  33.107 +		}
  33.108 +		hdr.size += res;
  33.109 +	}
  33.110 +
  33.111 +	io->seek(offset, SEEK_SET, io->cls);
  33.112 +	if(io->write(&hdr, hdr.size, io->cls) < hdr.size) {
  33.113 +		return -1;
  33.114 +	}
  33.115 +	return hdr.size;
  33.116 +}
  33.117 +
  33.118 +static long save_material(const Material *mat, long offset, goat3d_io *io)
  33.119 +{
  33.120 +	long res;
  33.121 +
  33.122 +	ChunkHeader hdr;
  33.123 +	hdr.id = CNK_MTL;
  33.124 +	hdr.size = sizeof hdr;
  33.125 +
  33.126 +	for(int i=0; i<mat->get_attrib_count(); i++) {
  33.127 +		const char *name = mat->get_attrib_name(i);
  33.128 +		if((res = save_mat_attrib(name, (*mat)[i], offset + hdr.size, io)) < 0) {
  33.129 +			return -1;
  33.130 +		}
  33.131 +		hdr.size += res;
  33.132 +	}
  33.133 +
  33.134 +	io->seek(offset, SEEK_SET, io->cls);
  33.135 +	if(io->write(&hdr, hdr.size, io->cls) < hdr.size) {
  33.136 +		return -1;
  33.137 +	}
  33.138 +	return hdr.size;
  33.139 +}
  33.140 +
  33.141 +static long save_mat_attrib(const char *name, const MaterialAttrib &attr, long offset, goat3d_io *io)
  33.142 +{
  33.143 +	long res;
  33.144 +
  33.145 +	ChunkHeader hdr;
  33.146 +	hdr.id = CNK_MTL_ATTR;
  33.147 +	hdr.size = sizeof hdr;
  33.148 +
  33.149 +	// TODO cont.
  33.150 +	return -1;
  33.151 +}
  33.152 +
  33.153 +static long save_meshes(const Scene *scn, long offset, goat3d_io *io)
  33.154 +{
  33.155 +	return 0;
  33.156 +}
  33.157 +
  33.158 +static long save_lights(const Scene *scn, long offset, goat3d_io *io)
  33.159 +{
  33.160 +	return 0;
  33.161 +}
  33.162 +
  33.163 +static long save_cameras(const Scene *scn, long offset, goat3d_io *io)
  33.164 +{
  33.165 +	return 0;
  33.166 +}
  33.167 +
  33.168 +static long save_nodes(const Scene *scn, long offset, goat3d_io *io)
  33.169 +{
  33.170 +	return 0;
  33.171 +}
  33.172 +
  33.173 +static long write_chunk_float(int id, float val, long offs, goat3d_io *io)
  33.174 +{
  33.175 +	int size = sizeof(ChunkHeader) + sizeof val;
  33.176 +	char *buf = (char*)alloca(size);
  33.177 +
  33.178 +	Chunk *c = (Chunk*)buf;
  33.179 +	c->hdr.id = id;
  33.180 +	c->hdr.size = size;
  33.181 +	*(float*)c->data = val;
  33.182 +
  33.183 +	io->seek(offs, SEEK_SET, io->cls);
  33.184 +	if(io->write(buf, size, io->cls) < size) {
  33.185 +		return -1;
  33.186 +	}
  33.187 +	return size;
  33.188 +}
  33.189 +
  33.190 +static long write_chunk_float3(int id, const Vector3 &vec, long offs, goat3d_io *io)
  33.191 +{
  33.192 +	int size = sizeof(ChunkHeader) + sizeof vec;
  33.193 +	char *buf = (char*)alloca(size);
  33.194 +
  33.195 +	Chunk *c = (Chunk*)buf;
  33.196 +	c->hdr.id = id;
  33.197 +	c->hdr.size = size;
  33.198 +	*(Vector3*)c->data = vec;
  33.199 +
  33.200 +	io->seek(offs, SEEK_SET, io->cls);
  33.201 +	if(io->write(buf, size, io->cls) < size) {
  33.202 +		return -1;
  33.203 +	}
  33.204 +	return size;
  33.205 +}
  33.206 +
  33.207 +static long write_chunk_float4(int id, const Vector4 &vec, long offs, goat3d_io *io)
  33.208 +{
  33.209 +	int size = sizeof(ChunkHeader) + sizeof vec;
  33.210 +	char *buf = (char*)alloca(size);
  33.211 +
  33.212 +	Chunk *c = (Chunk*)buf;
  33.213 +	c->hdr.id = id;
  33.214 +	c->hdr.size = size;
  33.215 +	*(Vector4*)c->data = vec;
  33.216 +
  33.217 +	io->seek(offs, SEEK_SET, io->cls);
  33.218 +	if(io->write(buf, size, io->cls) < size) {
  33.219 +		return -1;
  33.220 +	}
  33.221 +	return size;
  33.222 +}
  33.223 +#endif
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/src/goat3d_writexml.cc	Thu Sep 26 04:47:05 2013 +0300
    34.3 @@ -0,0 +1,187 @@
    34.4 +#include <stdarg.h>
    34.5 +#include "goat3d_impl.h"
    34.6 +#include "chunk.h"
    34.7 +#include "openctm.h"
    34.8 +
    34.9 +static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level);
   34.10 +static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level);
   34.11 +static void write_ctm_mesh(const Mesh *mesh, const char *fname);
   34.12 +static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level);
   34.13 +static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level);
   34.14 +static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level);
   34.15 +static void xmlout(goat3d_io *io, int level, const char *fmt, ...);
   34.16 +
   34.17 +bool Scene::savexml(goat3d_io *io) const
   34.18 +{
   34.19 +	xmlout(io, 0, "<scene>\n");
   34.20 +
   34.21 +	// write environment stuff
   34.22 +	xmlout(io, 1, "<env>\n");
   34.23 +	xmlout(io, 1, "</env>\n");
   34.24 +
   34.25 +	for(size_t i=0; i<materials.size(); i++) {
   34.26 +		write_material(this, io, materials[i], 1);
   34.27 +	}
   34.28 +	for(size_t i=0; i<meshes.size(); i++) {
   34.29 +		write_mesh(this, io, meshes[i], i, 1);
   34.30 +	}
   34.31 +	for(size_t i=0; i<lights.size(); i++) {
   34.32 +		write_light(this, io, lights[i], 1);
   34.33 +	}
   34.34 +	for(size_t i=0; i<cameras.size(); i++) {
   34.35 +		write_camera(this, io, cameras[i], 1);
   34.36 +	}
   34.37 +	for(size_t i=0; i<nodes.size(); i++) {
   34.38 +		write_node(this, io, nodes[i], 1);
   34.39 +	}
   34.40 +
   34.41 +	xmlout(io, 0, "</scene>\n");
   34.42 +	return true;
   34.43 +}
   34.44 +
   34.45 +static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level)
   34.46 +{
   34.47 +	xmlout(io, level, "<mtl>\n");
   34.48 +	xmlout(io, level + 1, "<name string=\"%s\"/>\n", mat->name.c_str());
   34.49 +
   34.50 +	for(int i=0; i<mat->get_attrib_count(); i++) {
   34.51 +		xmlout(io, level + 1, "<attr>\n");
   34.52 +		xmlout(io, level + 2, "<name string=\"%s\"/>\n", mat->get_attrib_name(i));
   34.53 +
   34.54 +		const MaterialAttrib &attr = (*mat)[i];
   34.55 +		xmlout(io, level + 2, "<val float4=\"%.3f %.3f %.3f\"/>\n", attr.value.x,
   34.56 +				attr.value.y, attr.value.z, attr.value.w);
   34.57 +		if(!attr.map.empty()) {
   34.58 +			xmlout(io, level + 2, "<map string=\"%s\"/>\n", attr.map.c_str());
   34.59 +		}
   34.60 +		xmlout(io, level + 1, "</attr>\n");
   34.61 +	}
   34.62 +	xmlout(io, level, "</mtl>\n");
   34.63 +	return true;
   34.64 +}
   34.65 +
   34.66 +static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level)
   34.67 +{
   34.68 +	// first write the external (openctm) mesh file
   34.69 +	const char *prefix = scn->get_name();
   34.70 +	if(!prefix) {
   34.71 +		prefix = "goat";
   34.72 +	}
   34.73 +
   34.74 +	char *mesh_filename = (char*)alloca(strlen(prefix) + 32);
   34.75 +	sprintf(mesh_filename, "%s-mesh%04d.ctm", prefix, idx);
   34.76 +
   34.77 +	write_ctm_mesh(mesh, mesh_filename);
   34.78 +
   34.79 +	// then refer to that filename in the XML tags
   34.80 +	xmlout(io, level, "<mesh>\n");
   34.81 +	xmlout(io, level + 1, "<name string=\"%s\"/>\n", mesh->name.c_str());
   34.82 +	xmlout(io, level + 1, "<material string=\"%s\"/>\n", mesh->material->name.c_str());
   34.83 +	xmlout(io, level + 1, "<file string=\"%s\"/>\n", mesh_filename);
   34.84 +	xmlout(io, level, "</mesh>\n");
   34.85 +	return true;
   34.86 +}
   34.87 +
   34.88 +static void write_ctm_mesh(const Mesh *mesh, const char *fname)
   34.89 +{
   34.90 +	int vnum = (int)mesh->vertices.size();
   34.91 +
   34.92 +	CTMcontext ctm = ctmNewContext(CTM_EXPORT);
   34.93 +
   34.94 +	// vertices, normals, and face-vertex indices
   34.95 +	ctmDefineMesh(ctm, &mesh->vertices[0].x, vnum, (CTMuint*)mesh->faces[0].v,
   34.96 +			mesh->faces.size(), mesh->normals.empty() ? 0 : &mesh->normals[0].x);
   34.97 +
   34.98 +	// texture coordinates
   34.99 +	if(!mesh->texcoords.empty()) {
  34.100 +		CTMfloat *uvarray = new CTMfloat[vnum * 2 * sizeof *uvarray];
  34.101 +		CTMfloat *uvptr = uvarray;
  34.102 +
  34.103 +		for(int i=0; i<vnum; i++) {
  34.104 +			*uvptr++ = mesh->texcoords[i].x;
  34.105 +			*uvptr++ = mesh->texcoords[i].y;
  34.106 +		}
  34.107 +		ctmAddUVMap(ctm, uvarray, "texcoord", 0);
  34.108 +		delete [] uvarray;
  34.109 +	}
  34.110 +
  34.111 +	// vertex colors
  34.112 +	if(!mesh->colors.empty()) {
  34.113 +		ctmAddAttribMap(ctm, &mesh->colors[0].x, "color");
  34.114 +	}
  34.115 +
  34.116 +	// skin weights
  34.117 +	if(!mesh->skin_weights.empty()) {
  34.118 +		ctmAddAttribMap(ctm, &mesh->skin_weights[0].x, "skin_weight");
  34.119 +	}
  34.120 +
  34.121 +	// if either of the non-float4 attributes are present we need to make a tmp array
  34.122 +	CTMfloat *attr_array = 0;
  34.123 +	if(!mesh->tangents.empty() || !mesh->skin_matrices.empty()) {
  34.124 +		attr_array = new CTMfloat[vnum * 4 * sizeof *attr_array];
  34.125 +	}
  34.126 +
  34.127 +	// tangents
  34.128 +	if(!mesh->tangents.empty()) {
  34.129 +		CTMfloat *ptr = attr_array;
  34.130 +
  34.131 +		for(int i=0; i<vnum; i++) {
  34.132 +			*ptr++ = mesh->tangents[i].x;
  34.133 +			*ptr++ = mesh->tangents[i].y;
  34.134 +			*ptr++ = mesh->tangents[i].z;
  34.135 +			*ptr++ = 1.0;
  34.136 +		}
  34.137 +		ctmAddAttribMap(ctm, attr_array, "tangent");
  34.138 +	}
  34.139 +
  34.140 +	// skin matrix indices (4 per vertex)
  34.141 +	if(!mesh->skin_matrices.empty()) {
  34.142 +		CTMfloat *ptr = attr_array;
  34.143 +
  34.144 +		for(int i=0; i<vnum; i++) {
  34.145 +			*ptr++ = (float)mesh->skin_matrices[i].x;
  34.146 +			*ptr++ = (float)mesh->skin_matrices[i].y;
  34.147 +			*ptr++ = (float)mesh->skin_matrices[i].z;
  34.148 +			*ptr++ = (float)mesh->skin_matrices[i].w;
  34.149 +		}
  34.150 +		ctmAddAttribMap(ctm, attr_array, "skin_matrix");
  34.151 +	}
  34.152 +
  34.153 +	delete [] attr_array;
  34.154 +
  34.155 +	/* TODO find a way to specify the nodes participating in the skinning of this mesh
  34.156 +	 * probably in the comment field?
  34.157 +	 */
  34.158 +
  34.159 +	ctmSave(ctm, fname);
  34.160 +
  34.161 +	ctmFreeContext(ctm);
  34.162 +}
  34.163 +
  34.164 +static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level)
  34.165 +{
  34.166 +	return true;
  34.167 +}
  34.168 +
  34.169 +static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level)
  34.170 +{
  34.171 +	return true;
  34.172 +}
  34.173 +
  34.174 +static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level)
  34.175 +{
  34.176 +	return true;
  34.177 +}
  34.178 +
  34.179 +
  34.180 +static void xmlout(goat3d_io *io, int level, const char *fmt, ...)
  34.181 +{
  34.182 +	for(int i=0; i<level; i++) {
  34.183 +		io_fprintf(io, "  ");
  34.184 +	}
  34.185 +
  34.186 +	va_list ap;
  34.187 +	va_start(ap, fmt);
  34.188 +	io_vfprintf(io, fmt, ap);
  34.189 +	va_end(ap);
  34.190 +}