diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luapplib')
141 files changed, 14717 insertions, 7829 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/.gitattributes b/Build/source/texk/web2c/luatexdir/luapplib/.gitattributes new file mode 100644 index 00000000000..8d68adf9ae9 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/.gitattributes @@ -0,0 +1,10 @@ +*.c text=auto eol=lf +*.h text=auto eol=lf +Makefile text=auto eol=lf + +*.rst binary +*.png binary +*.jpg binary +*.css binary +*.html binary +*.js binary
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/.gitignore b/Build/source/texk/web2c/luatexdir/luapplib/.gitignore new file mode 100644 index 00000000000..84d76071422 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/.gitignore @@ -0,0 +1,8 @@ +src/build/* +src/CMakeFiles/* +src/CMakeCache.txt +src/.vs/* +src/.cproject +src/.project +src/.settings +zlib/*
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/.gitmodules b/Build/source/texk/web2c/luatexdir/luapplib/.gitmodules new file mode 100644 index 00000000000..4792336ecfc --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/.gitmodules @@ -0,0 +1,3 @@ +[submodule "zlib"] + path = zlib + url = git://github.com/madler/zlib.git diff --git a/Build/source/texk/web2c/luatexdir/luapplib/.travis.yml b/Build/source/texk/web2c/luatexdir/luapplib/.travis.yml new file mode 100644 index 00000000000..2f1c9a01cbc --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/.travis.yml @@ -0,0 +1,20 @@ +language: c + +script: + - mkdir build + - cd build + - cmake .. + - make -j 2 + - make -j 2 test + +matrix: + include: + - os: linux + compiler: clang + - os: linux + compiler: gcc + - os: osx + osx_image: xcode10.2 + allow_failures: + - os: osx + osx_image: xcode8 diff --git a/Build/source/texk/web2c/luatexdir/luapplib/CMakeLists.txt b/Build/source/texk/web2c/luatexdir/luapplib/CMakeLists.txt new file mode 100644 index 00000000000..8c2ea1e89ae --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.5) + +add_subdirectory(zlib) +add_subdirectory(src) + +enable_testing() diff --git a/Build/source/texk/web2c/luatexdir/luapplib/README.md b/Build/source/texk/web2c/luatexdir/luapplib/README.md new file mode 100644 index 00000000000..c684e9ed7ce --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/README.md @@ -0,0 +1,9 @@ +## pplib - pdf disassembling library for LuaTeX + +This is `plib` - PDF disassembling library for LuaTeX (http://luatex.org) + +The library has no LuaTeX dependency, it depends only on `zlib`. +However, `pplib` was tailor-made for LuaTeX and its functionals are +somewhat limited (eg. read-only PDF support). + +Author: Paweł Jackowski p.jackowski@gust.org.pl diff --git a/Build/source/texk/web2c/luatexdir/luapplib/azure-pipelines.yml b/Build/source/texk/web2c/luatexdir/luapplib/azure-pipelines.yml new file mode 100644 index 00000000000..365abe00716 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/azure-pipelines.yml @@ -0,0 +1,36 @@ +# C/C++ with GCC +# Build your C/C++ project with GCC using make. +# Add steps that publish test results, save build artifacts, deploy, and more: +# https://docs.microsoft.com/azure/devops/pipelines/apps/c-cpp/gcc + +trigger: +- master + +jobs: + +- job: Build + + strategy: + matrix: + linux: + imageName: "ubuntu-16.04" + mac: + imageName: "macos-10.13" + windows: + imageName: "vs2017-win2016" + maxParallel: 3 + + pool: + vmImage: $(imageName) + + steps: + - checkout: self + submodules: recursive + - task: CMake@1 + displayName: 'CMake ..' + inputs: + cmakeArgs: '..' + - task: CMake@1 + displayName: 'CMake --build . --config Debug' + inputs: + cmakeArgs: '--build . --config Debug' diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/Makefile b/Build/source/texk/web2c/luatexdir/luapplib/doc/Makefile new file mode 100644 index 00000000000..3ca7eeebf89 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = pplib +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/environment.pickle b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/environment.pickle Binary files differnew file mode 100644 index 00000000000..c4d657a1115 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/environment.pickle diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppapi-1.x.doctree b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppapi-1.x.doctree Binary files differnew file mode 100644 index 00000000000..bd22032c659 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppapi-1.x.doctree diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppapi-2.x.doctree b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppapi-2.x.doctree Binary files differnew file mode 100644 index 00000000000..d8c91b48bed --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppapi-2.x.doctree diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppapi.doctree b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppapi.doctree Binary files differnew file mode 100644 index 00000000000..9e432d80125 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppapi.doctree diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppcode.doctree b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppcode.doctree Binary files differnew file mode 100644 index 00000000000..a33b506208e --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppcode.doctree diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/pplib.doctree b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/pplib.doctree Binary files differnew file mode 100644 index 00000000000..0d5e84fe5a5 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/pplib.doctree diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppnew.doctree b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppnew.doctree Binary files differnew file mode 100644 index 00000000000..5c152d321a5 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/doctrees/ppnew.doctree diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/.buildinfo b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/.buildinfo index 13665a90458..ec014001dee 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/.buildinfo +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
-config: 96901ec9cd68906e4f139a0be4b45fcc
+config: 5a0a9f8c8bb0798c3d499fe9e55f5963
tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppapi-1.x.rst.txt b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppapi-1.x.rst.txt new file mode 100644 index 00000000000..df661a7b82d --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppapi-1.x.rst.txt @@ -0,0 +1,937 @@ +
+``pplib`` 1.x
+=============
+
+``pplib`` is a library for raw PDF access. It parses PDF documents and provides an interface to access document structures in C.
+
+C-API
+=====
+
+Types
+-----
+
+``pplib`` defines several C-types to represent PDF types:
+
+- ``ppint`` - signed integer (``int64_t``)
+- ``ppnum`` - real number (double)
+- ``ppname`` - PDF name
+- ``ppstring`` - PDF string
+- ``pparray`` - PDF array
+- ``ppdict`` - PDF dict
+- ``ppstream`` - PDF stream
+- ``ppref`` - PDF indirect reference
+- ``ppobj`` - a container of all above
+
+Among ``ppint`` and ``ppnum``, we also use ``ppuint`` - unsigned integer (machine word, alias to ``size_t``).
+
+Other API types:
+
+- ``ppdoc`` - PDF document
+- ``ppxref`` - cross-references table
+- ``ppcontext`` - ... later
+- ``pprect`` - rectangle
+- ``ppmatrix`` - matrix
+
+Integer, number, name and string are treated as simple types.
+Names and strings are actually C-structures, but exposed to API as typedefs to ``const char *``.
+Other types (array, dict, stream, reference, object container, xref, PDF) are C-structures,
+and you operate it their pointers. So when you declare a simple type variable you say::
+
+ ppuint u;
+ ppnum n;
+ ppname name;
+ ppstring string;
+ ...
+
+And when you declare a compound type you operate on pointers::
+
+ ppobj *obj;
+ pparray *array;
+ ppdict *dict;
+ ppstream *stream;
+ ppref *ref;
+ ppdoc *pdf;
+
+Some of those C-types are defined in library header ``ppapi.h`` (complete types). Some others are incomplete
+(eg. you can't say ``sizeof(ppdoc)`` or ``sizeof(ppxref)``). This is to avoid unnecesary dependencies in
+the header. [At some points it's not clear to me what to hide and what to expose, will see.] The library itself
+uses ``pplib.h`` but for auxilary applications including a standalone ``ppapi.h`` header should be enough.
+
+``pplib`` was designed having **read-only** PDF access in mind. Even if some structure is completelly exposed,
+so that you can directly access its members, you should treat them as read-only. I don't make them ``const`` because
+then all variable declarations would need to be ``const``, which is annoying, and I'd need some trickery in the library
+internals to unconst. Besides, nothing is really const for C type casts.
+
+Object
+------
+
+A common container for all elementary PDF object types is ``ppobj`` structure. ``ppobj`` has a type identifier
+(integer) and union of values::
+
+ struct ppobj {
+ ppobjtp type;
+ union {
+ ppint integer;
+ ppnum number;
+ ppname name;
+ ppstring string;
+ pparray *array;
+ ppdict *dict;
+ ppstream *stream;
+ ppref *ref;
+ void *any;
+ };
+ };
+
+Object type is one of constants (enum)::
+
+ PPNONE
+ PPNULL
+ PPBOOL
+ PPINT
+ PPNUM
+ PPNAME
+ PPSTRING
+ PPARRAY
+ PPDICT
+ PPSTREAM
+ PPREF
+
+The type determines the structure member you're allowed to access::
+
+ ppobj *obj;
+ ...
+ switch (obj->type)
+ {
+ case PPNONE: // shouldn't actually happen, indicates some failure
+ break;
+ case PPNULL: // valid PDF null object, no value
+ break;
+ case PPBOOL: // do something with obj->integer (ppint), value 0 or 1
+ break;
+ case PPINT: // do something with obj->integer (ppint)
+ break;
+ case PPNUM: // do something with obj->number (ppnum)
+ break;
+ case PPNAME: // do something with obj->name (ppname)
+ break;
+ case PPSTRING: // do something with obj->string (ppstring)
+ break;
+ case PPARRAY: // do something with obj->array (pparray *)
+ break;
+ case PPDICT: // do something with obj->dict (ppdict *)
+ break;
+ case PPSTREAM: // do something with obj->stream (ppstream *)
+ break;
+ case PPREF: // do something with obj->ref (ppref *)
+ break;
+ }
+
+More often then not you know exactly what type of object value is expected, in which case
+you may use one of the following macros::
+
+ // returns 1 if o->type is PPNULL
+ int ppobj_get_null(o) \
+
+ // if o->type is PPBOOL, sets int v to 0 or 1 and returns 1, 0 otherwise
+ int ppobj_get_bool(o, v)
+
+ // if o->type is PPINT, sets ppint v and returns 1, 0 otherwise
+ int ppobj_get_int(o, v)
+
+ // if o->type is PPINT and >= 0, sets ppuint v and returns 1, 0 otherwise
+ int ppobj_get_uint(o, v)
+
+ // if o->type is PPNUM or PPINT, sets ppnum v and returns 1, 0 otherwise
+ int ppobj_get_num(o, v)
+
+ // if o->type is PPNAME returns the name, NULL otherwise
+ ppname ppobj_get_name(o)
+
+ // if o->type is PPSTRING returns the string, NULL otherwise
+ ppstring ppobj_get_string(o)
+
+ // if o->type is PPARRAY returns the array, NULL otherwise
+ pparray * ppobj_get_array(o)
+
+ // if o->type is PPDICT returns the dict, NULL otherwise
+ ppdict * ppobj_get_dict(o)
+
+ // if o->type is PPSTREAM returns the stream, NULL otherwise
+ ppstream * ppobj_get_stream(o)
+
+ // if o->type is PPREF returns the reference, NULL otherwise
+ ppref * ppobj_get_ref(o)
+
+Note the coercion from integer to real number, but not reverse. In practise, whenever you expect a real number,
+you should also handle integer (eg. '1' used instead of '1.0').
+
+It is a common case that the object is given as an indirect reference, but what you actually
+want is not the reference, but the object referred by it. Here is a helper for it::
+
+ // if o->type is PPREF, returns what the reference points, otherwise returns o
+ ppobj * ppobj_rget_obj(o)
+
+Also every ``ppobj_get_*`` macro has ``ppobj_rget_*`` counterpart that makes a check
+for the expected type, but if the object is PPREF, it jumps to the target object.
+So for example ``ppobj_rget_dict(obj)`` will return dict if ``obj`` is of type PPDICT
+or if it is of type PPREF and ``obj->ref`` hosts an object of type PPDICT.
+
+Names
+-----
+
+PDF names are represented as ``ppname``.
+I find it convenient to have ``ppname`` type pretending ``const char *``. This allows to use ``ppname``
+in all C-style string functions like ``printf("%s", name)``.
+
+Be aware, however, that ``ppname`` is actually a C-structure. It is perfectly ok to cast ``ppname`` to ``const char *``::
+
+ ppname name;
+ ...
+ (const char *)name;
+
+But reverse is forbidden::
+
+ const char *cstr = "cstring";
+ ...
+ (ppname)cstr; // expect segmentation fault soon
+
+For convenient use in C, names are ``'\0'`` terminated. But to get the length of name better always use
+``ppname_size()`` macro. ``ppname`` object knows its size, don't use ``strlen()``::
+
+ size_t ppname_size(ppname name); // macro, returns length of name in bytes
+
+In current implementation names are not hashed anyhow, so name-to-name comparison is not smarter than ``memcmp()``.
+Use macros::
+
+ int ppname_is(ppname name, "literal"); // to compare ppname with C-literal string
+ int ppname_eq(ppname name, ppname other); // to compare ppname with a different name
+
+If you'll use ``pplib`` to parse contents streams, you may need to distinguish names from operators
+(more precisely executable names). Names in PDF are preceeded by '/', executable names aren't. In both
+cases PDF parser will produce ``ppname`` but can be distingushed with::
+
+ int ppname_exec(ppname name); // returns non-zero if name is executable
+
+Names are kept in their raw form, with possible PDF specific escapes (in text below we call it **encoded** form).
+Leading '/' is omitted, though. One may need a decoded name, with no PDF escapes.
+A pair of functions provides a simple interface to switch between those two forms::
+
+ ppname ppname_decoded (ppname name); // returns decoded (unescaped) form of the name
+ ppname ppname_encoded (ppname name); // returns encoded (escaped) form of the name
+
+In pretty most cases PDF names contains only letters (no special characters, no escapes), so decoded and encoded forms are identical.
+In that case both functions simply return the argument. It is ok to call ``ppname_decoded()`` on already decoded form
+and ``ppname_encoded()`` on already encoded form. Both forms are produced by PDF objects parser, so accessing ``ppname`` alter ego
+in whatever direction needs no extra decoding or allocation costs.
+
+String
+------
+
+PDF strings have the same internal construction as names, so most of names description above applies to strings as well.
+``ppstring`` is a typedef of ``const char *``, roughly ``'\0'`` terminiated C-string. To get the size of the string::
+
+ size_t ppstring_size(ppstring string); // macro, returns the length of the string in bytes
+
+Strings are provided in their raw form, preserving PDF specific escapes, but with no
+``()`` or ``<>`` delims. To distinguish plain strings from hex strings::
+
+ int ppstring_hex(ppstring string); // macro, returns non zero if hex string
+
+Or if you prefer::
+
+ switch (ppstring_type(string))
+ {
+ case PPSTRING_PLAIN: // literal string, surrounded by ``(`` and ``)`` in PDF
+ break;
+ case PPSTRING_BASE16: // hex string, surrounded by ``<`` and ``>`` in PDF
+ break;
+ case PPSTRING_BASE85: // base85 string surrounded by ``<~`` and ``~>`` in PDF
+ break;
+ }
+
+The last is actually Postscript specific, not used in PDF, but I think it might appear in contents streams...
+No matter how the string is given in PDF (plain or hex), here are two functions to
+switch between encoded and decoded strings forms::
+
+ ppstring ppstring_decoded (ppstring string); // returns decoded string possibly with PDF escapes
+ ppstring ppstring_encoded (ppstring string); // returns encoded string with no PDF escapes
+
+For hex strings, encoded form contains hex digits, while decoded form contains arbitrary bytes (the result of hex decoding).
+Plain strings usually contains printable ASCII characters, but they might contain any binary data.
+As with names, objects parser produces both forms. The raw form with PDF escapes (or raw hex form) is considered the main one.
+Eg. when you access ``obj->string`` you always get the encoded form. At any moment you can switch to its alter ego.
+
+No matter if the string is plain or hex, if its first two bytes (decoded) are UTF16 BOM, the string
+is considered unicode. ``ppstring`` object *knows* it is unicode or not::
+
+ switch (ppstring_utf(string))
+ {
+ case PPSTRING_UTF16LE: // unicode string, utf16le
+ break;
+ case PPSTRING_UTF16BE: // unicode string, utf16be
+ break;
+ default: // no unicode
+ }
+
+Or simply::
+
+ if (ppstring_utf(string) != 0) {
+ // handle unicode string
+ }
+
+If the string is unicode, BOM remains the part of the string -- ``pplib`` parser does not strip it.
+Unicode or not, encoded or decoded, strings are always C-arrays of bytes and ``ppstring_size()``
+always returns the size in bytes.
+
+Array
+-----
+
+PDF arrays are represented as ``pparray`` type, which is C-array of ``ppobj`` structures.
+To get the size::
+
+ size_t pparray_size(pparray *array) // macro, returns the number of array items
+
+To get ``ppobj *`` at a given index::
+
+ ppobj * pparray_at(array, index) // macro, returns ppobj * (no index check)
+ ppobj * pparray_get(array, index) // macro, returns ppobj * or NULL (with index check)
+ ppobj * pparray_get_obj (pparray *array, size_t index); // function equiv to pparray_get()
+
+Iterating over array elements::
+
+ pparray *array;
+ size_t index, size;
+ ppobj *obj;
+ for (size = pparray_size(array), pparray_first(array, index, obj); index < size; pparray_next(index, obj))
+ {
+ // do something with index and obj
+ }
+
+There is no magic first/next macros, just iteration over pointers. One could also use something like::
+
+ for (index = 0, size = array->size; index < size; ++index)
+ {
+ obj = pparray_at(array, index);
+ // do something with index and obj
+ }
+
+When getting values from array and expecting a result of known type, use one of the following::
+
+ int pparray_get_bool (pparray *array, size_t index, int *v); // get boolean value
+ int pparray_get_int (pparray *array, size_t index, ppint *v); // get ppint value
+ int pparray_get_uint (pparray *array, size_t index, ppuint *v); // get ppuint value
+ int pparray_get_num (pparray *array, size_t index, ppnum *v); // get ppnum value
+ ppname pparray_get_name (pparray *array, size_t index); // get ppname value
+ ppstring pparray_get_string (pparray *array, size_t index); // get ppstring value
+ pparray * pparray_get_array (pparray *array, size_t index); // get pparray * value
+ ppdict * pparray_get_dict (pparray *array, size_t index); // get ppdict * value
+ ppref * pparray_get_ref (pparray *array, size_t index); // get ppref * value
+
+As with ``ppobj_get_*`` suite, numeric types getters set the value of a given type and returns 1, if the type matches.
+Otherwise sets nothing and returns 0. Other getters return the value if the type matches, or NULL.
+
+Every function from ``pparray_get_*`` suite have its ``pparray_rget_*`` counterpart that
+that dereferences indirect objects (as explained for ``ppobj_rget_*`` getters). Note that
+there is no ``pparray_get_stream()`` function, as streams in PDF are always indirect.
+To get the stream from array use::
+
+ ppstream * pparray_rget_stream (pparray *array, size_t index);
+
+Dict
+----
+
+PDF dicts are represented as ``ppdict`` structure, which is C-array of ``ppobj`` with parallel
+C-array of ``ppname`` pointers. To get the size of a dict::
+
+ size_t ppdict_size(ppdict *dict) // macro, returns the number of key-val pairs
+
+To get the value at a given index (integer)::
+
+ ppobj * ppdict_at(ppdict *dict, index) // macro, no index check
+
+To get the name (key) at a given index::
+
+ ppname ppdict_key(ppdict *dict, index) // macro, no index check
+
+To iterate over dict key-val pairs::
+
+ ppdict *dict;
+ ppname *pkey;
+ ppobj *obj;
+
+ for (ppdict_first(dict, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj))
+ {
+ // do something with *pkey and obj
+ }
+
+There is no magic in first/next macros, just iteration through keys and values lists pointers.
+For convenient iteration, a list of keys is terminated with NULL, so in the code above ``*pkey != NULL``
+is used as the loop condition. One may also iterate via indices::
+
+ ppdict *dict;
+ size_t index, size;
+ ppname key;
+ ppobj *obj;
+ for (index = 0, size = ppdict_size(dict); index < size; ++index)
+ {
+ key = ppdict_key(dict, index);
+ obj = ppdict_at(dict, index);
+ // do something with key and obj
+ }
+
+To get the object associated with a given name, use one of the following::
+
+ ppobj * ppdict_get_obj (ppdict *dict, const char *name);
+ int ppdict_get_bool (ppdict *dict, const char *name, int *v);
+ int ppdict_get_int (ppdict *dict, const char *name, ppint *v);
+ int ppdict_get_uint (ppdict *dict, const char *name, ppuint *v);
+ int ppdict_get_num (ppdict *dict, const char *name, ppnum *v);
+ ppname ppdict_get_name (ppdict *dict, const char *name);
+ ppstring ppdict_get_string (ppdict *dict, const char *name);
+ pparray * ppdict_get_array (ppdict *dict, const char *name);
+ ppdict * ppdict_get_dict (ppdict *dict, const char *name);
+ ppref * ppdict_get_ref (ppdict *dict, const char *name);
+
+Note that all getters accepts ``const char *`` as key, so it is ok to say::
+
+ ppdict_rget_dict(dict, "Resources");
+
+as well as::
+
+ ppdic_rget_dict(dict, name); // ppname name
+
+Every ``ppdict_get_*`` getter has ``ppdict_rget_*`` counterpart that dereferences
+indirect objects if necessary. Note that there is no ``ppdict_get_stream()`` function,
+but there is::
+
+ ppstream * ppdict_rget_stream (ppdict *dict, const char *name);
+
+So far dicts comes with no names mapping, so by-name dict accessors perform a linear search
+through the keys list. PDF dicts are usually small, so it is fast enough.
+Building names lookup for every dict in PDF makes no sense I think, as ``pplib`` applications
+will query just several dicts I guess.. However, some apps may extensively query
+resources, which may refer to hundreds of objects (eg. images). So some mapping for dicts
+is still considered.
+
+Stream
+------
+
+PDF streams are represented as ``ppstream`` objects. To get the stream dict::
+
+ ppdict * ppstream_dict(ppstream *stream) // macro
+
+To read the stream data::
+
+ uint8_t * ppstream_first (ppstream *stream, size_t *size, int decode);
+ uint8_t * ppstream_next (ppstream *stream, size_t *size);
+ void ppstream_done (ppstream *stream);
+
+Both ``first` and ``next`` functions return a chunk of stream data and sets the ``size`` of the chunk.
+``decode`` parameter tell the reader to decompress the stream (1) or return raw (0). A call to ``ppstream_next()``
+must be preceeded by ``ppstream_first()``. Once you're done with the stream, you have to call ``ppstream_done()``,
+no matter if the stream has been read to the end or not. The stream data iterator in use::
+
+ uint8_t *data;
+ size_t size;
+ ppstream *stream;
+ int decode = 1; // 1 - get decompressed, 0 - get raw
+
+ for (data = ppstream_first(stream, &size, decode); data != NULL; data = ppstream_next(stream, &size))
+ {
+ // do something with data and its size
+ }
+ ppstream_done(stream);
+
+Every subsequent iterator call invalidates the previous reader output, so you have to utilize the returned chunk
+of data just after you ot that. So the following is wrong::
+
+ data1 = ppstream_first(stream, &size, 1);
+ data2 = ppstream_next(stream, &size);
+ data3 = ppstream_next(stream, &size);
+ some_output(data1, size);
+ some_output(data2, size);
+
+The reader calls usually return the same pointer to internal buffer, just filled with a different data.
+``pplib`` allocates reasonably large buffer and fills that buffer on subsequent calls to the reader.
+
+If the source stream has no compression, using both ``decode == 1`` and ``decode == 0`` should give the same result.
+You can check if the stream is actually compressed with::
+
+ ppstream_compressed(stream) // macro, returns non zero if /Filter is present
+
+It might be necessary to load the entire stream data at once::
+
+ uint8_t * ppstream_all (ppstream *stream, size_t *size, int decode);
+
+If the initial buffer size is insufficient, it grows until the entire stream data is loaded. You must call
+``ppstream_done(stream)`` after using returned data.
+
+``ppstream_done()`` doesn't invalidate the stream object, it just closes its internal reader.
+The stream itself remains a valid object (eg. one can read it again if necessary),
+but the reader buffer is released. It is actually not freed but kept for future the reuse with that on some other stream,
+but you still need to mark it ready for reuse to avoid allocating a separate buffer for every stream you're going to read.
+
+Stream data readers will return ``NULL`` if you haven't close the previous reader process with ``ppstream_done()``. All below is wrong::
+
+ data1 = ppstream_all(stream, &size, 1);
+ data2 = ppstream_all(stream, &size, 1); // data2 == NULL
+ // or
+ data1 = ppstream_first(stream, &size, 1);
+ data2 = ppstream_first(stream, &size, 1); // data2 == NULL
+ // or
+ data1 = ppstream_first(stream, &size, 1);
+ data2 = ppstream_all(stream, &size, 1); // data2 == NULL
+
+To avoid unnecessary dependencies, ``pplib`` does not support image filters (``/DCT``, ``/JPX``, ``/JBIG``, ``/CCITT``).
+But it is ok to read the stream with ``decode`` set to 1 on such streams. ``pplib`` assumes that the image is the
+final/target stream form and just returns it as-is. Eg. in the case of JPEG (``/DCT`` filtered) image both calls should
+give the same results::
+
+ ppstream_all(jpegstream, &jpegsize, 0); // don't decode, return what's there
+ ppstream_all(jpegstream, &jpegsize, 1); // decode but found image filter, effectively the same
+
+A bit more about streams memory. As mentioned, ``pplib`` allocates buffers for stream readers. After ``ppstream_done()``,
+the stream no longer *owns* the buffer space. But the buffer may remain allocated, to be reused with future readers.
+``pplib`` keeps a pool of several buffers. This means, that when you use stream readers, ``pplib`` eats
+some memory (1MB or so) that is not freed, even if no streams are used. And even if you free all objects.
+If you suffer from this, you can optionally use a pair of functions::
+
+ void ppstream_init_buffers (void);
+ void ppstream_free_buffers (void);
+
+The first initializes buffers pool, unless done so far. Currently ``pplib`` cares of it before opening every stream reader,
+so it is not obligatory. The second frees a pool of buffers. The intended use is to call ``ppstream_init_buffers()`` once
+as kind of library initializer and to call ``ppstream_free_buffers()`` once, as the library finalizer.
+
+Filters
+-------
+
+In version v1.00 (20190916) ``ppstream`` API has been extended with filters information.
+``ppstream`` knows its filter(s) and keps it as ``stream->filter``::
+
+ // ppstream *stream;
+ ppstream_filter *info = &stream->filter;
+
+``ppstream_filter`` is the following structure::
+
+ typedef struct {
+ ppstreamtp *filters; // c-array of filter identifiers (enum integers)
+ ppdict **params; // c-array of ppdict pointers
+ size_t count; // number of filters, length of the arrays (typically 1)
+ } ppstream_filter;
+
+If ``count > 0`` then ``filters`` member is not NULL. Filters array keeps integer constants::
+
+ PPSTREAM_BASE16 /* /ASCIIHexDecode */
+ PPSTREAM_BASE85 /* /ASCII85Decode */
+ PPSTREAM_RUNLENGTH /* /RunLengthDecode */
+ PPSTREAM_FLATE /* /FlateDecode */
+ PPSTREAM_LZW /* /LZWDecode */
+ PPSTREAM_CCITT /* /CCITTFaxDecode */
+ PPSTREAM_DCT /* /DCTDecode */
+ PPSTREAM_JBIG2 /* /JBIG2Decode */
+ PPSTREAM_JPX /* /JPXDecode */
+ PPSTREAM_CRYPT /* /Crypt */
+
+Params array keeps corresponding filter parameters (``/DecodeParms``) if present. ``params`` member is not NULL
+if ``count > 0`` and the stream dict has ``/DecodeParms`` entry. Even if ``params`` is there,
+for every N-th filter, ``params[N]`` may be NULL (corresponding to PDF ``null``).
+
+``stream->filter`` keeps the source stream filter information, which may not correspond to the result of stream readers
+(``ppstream_first()``, ``ppstream_next()``, ``ppstream_all()``). The get the filters info relevant to the result from readers::
+
+ void ppstream_filter_info (ppstream *stream, ppstream_filter *info, int decode);
+
+The function fills ``ppstream_filter`` structure according to the expected result from stream readers (example 3 shows
+how to use it to reconstruct ``/Filter`` and ``/DecodeParms`` when copying the stream to some other PDF).
+
+To convert filter identifier (``ppstreamtp``) to a corresponding PDF filter name::
+
+ const char * ppstream_filter_name[];
+
+To covert ``ppname`` to filter identifier::
+
+ int ppstream_filter_type (ppname filtername, ppstreamtp *filtertype);
+ // returns 1 and sets filtertype if filtername is the proper filter name
+
+Additional information about the stream can be fetched from macros::
+
+ ppstream_compressed(stream) /* stream->flags & (PPSTREAM_FILTER|PPSTREAM_IMAGE) */
+ ppstream_filtered(stream) /* stream->flags & PPSTREAM_FILTER */
+ ppstream_image(stream) /* stream->flags * PPSTREAM_IMAGE */
+
+``stream->flags`` is a binary sum of the following::
+
+ PPSTREAM_FILTER /* set iff the stream filters list has one of: BASE16, BASE85, RUNLENGTH, FLATE, LZW */
+ PPSTREAM_IMAGE /* set iff the stream filters list has one of: CCITT, DCT, JBIG2, JPX */
+ PPSTREAM_ENCRYPTED /* set iff the stream is encrypted */
+ PPSTREAM_ENCRYPTED_OWN /* set iff the stream has own CRYPT filter */
+
+Note that ``PPSTREAM_COMPRESSED`` is not there any longer, use ``ppstream_compressed()`` instead.
+And there is some more, see ``ppapi.h``.
+
+Ref
+---
+
+Indirect objects are represented as ``ppref`` structure. To get the object that the
+reference refers to::
+
+ ppobj * ppref_obj(ppref *ref) // macro
+
+``ppref`` structure also keeps the reference number and version, a pointer to cross reference table it belongs
+to and others, but I guess you won't need anything but the referenced object. ``pplib`` parser resolves references
+on-fly. So if there is a dict with indirect objects::
+
+ <<
+ /Type /Page
+ /Resources 123 0 R
+ ...
+ >>
+
+the parser will produce ``ppdict`` with ``Resources`` key pointing the proper ``ppref *`` value.
+If you need more, access ``ppref`` members::
+
+ struct ppref {
+ ppobj object; // target object
+ ppuint number, version; // identifiers
+ size_t offset; // file offset (useless for you, may be zero for compressed objects)
+ ppuint length; // the length of the original object data
+ ppxref *xref; // cross reference table it belongs to
+ };
+
+
+XRef
+----
+
+Cross reference table is exposed as ``ppxref`` (incomplete type, you can only oprate on its pointer).
+To get top document xref::
+
+ ppxref * ppdoc_xref (ppdoc *pdf);
+
+To get previous (older) xref::
+
+ ppxref * ppxref_prev (ppxref *xref);
+
+To find an object of a given refnumber::
+
+ ppref * ppxref_find (ppxref *xref, ppuint refnumber);
+
+[Note: since pplib v0.98 in case of documents with incremental update, ``ppxref_find()`` returns
+the newest available version of a given object rather than the object in a given body.]
+
+PDF
+---
+
+PDF document is represented as ``ppdoc`` structure (incomplete type, you can only operate on its pointer).
+To load a document from file::
+
+ ppdoc * ppdoc_load (const char *filename);
+
+To load a document from memory data::
+
+ ppdoc * ppdoc_mem (const void *data, size_t size);
+
+The data is assumed to be a buffer allocated with ``malloc`` - it is freed when destroying ``ppdoc``.
+
+Both loaders returns ``NULL`` on failure.
+
+To free ``ppdoc`` and all objects it refers to::
+
+ void ppdoc_free (ppdoc *pdf);
+
+So far we haven't mention about any explicit object reclaimers. There are no dedicated ``free`` functions
+for other objects. You don't allocate or free objects yourself. ``ppdoc`` object is an owner of all
+beings it refers to. It also means that every object described so far is alive as long as the containing
+``ppdoc`` is alive.
+
+To access main PDF dicts::
+
+ ppdict * ppdoc_trailer(ppdoc *pdf); // returns top xref trailer dict
+ ppdict * ppdoc_catalog(ppdoc *pdf); // returns catalog referred from the trailer
+ ppdict * ppdoc_info(ppdoc *pdf); // returns info dict referred from the trailer
+
+To get the PDF version::
+
+ const char * ppdoc_version_string (ppdoc *pdf); // version string
+ int ppdoc_version_number (ppdoc *pdf, int *minor); // minor and major numbers
+
+To get the file size of the source PDF document::
+
+ size_t ppdoc_file_size (ppdoc *pdf);
+
+To get the number of objects in all xrefs::
+
+ ppuint ppdoc_objects (ppdoc *pdf);
+
+To get the approx usage of memory::
+
+ size_t ppdoc_memory (ppdoc *pdf, size_t *waste);
+
+Encryption
+----------
+
+``pplib`` handles encrypted (password protected) documents. If a document is encrypted, most of strings and streams are ciphered.
+In that form they are unreadable and rather useless, you can't even rewrite such strings/streams as-is to a different PDF output.
+It is a common practise to *protect* documents with an empty password. Such documents remain readable in Acrobat (just opens them without prompting
+for a password), but some features (eg. printing) may restricted by the application.
+
+When ``pplib`` detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, ``pplib`` proceeeds normally, providing
+an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, ``pplib`` gives
+a way to provide a password and proceed. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object wntries
+set to ``null``.
+
+After loading a document you should check encryption status with::
+
+ ppcrypt_status ppdoc_crypt_status (ppdoc *pdf);
+
+``ppcrypt_status`` (integer) may have the following values:
+
+ ``PPCRYPT_NONE`` - no encryption, go ahead
+ ``PPCRYPT_DONE`` - encryption present but password succeeded, go ahead
+ ``PPCRYPT_PASS`` - encryption present, need non-empty password
+ ``PPCRYPT_FAIL`` - invalid or unsupported encryption (eg. undocumented in pdf spec)
+
+If a password is needed, you can provide one with::
+
+ ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength,
+ const void *ownerpass, size_t ownerpasslength);
+
+Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough
+to know that having one of them is enough to decrypt the document. If you know the password, you probably mean
+``userpass``, in which case you should put ``NULL`` as ``ownerpass``. The function returns ``PPCRYPT_DONE`` if the password
+succeeds and the previous status otherwise. Your custom loader function may look like that::
+
+ ppdoc *pdf;
+ pdf = ppdoc_load("file.pdf");
+ if (pdf == NULL)
+ return NULL;
+ switch (ppdoc_crypt_status(pdf))
+ {
+ case PPCRYPT_NONE:
+ case PPCRYPT_DONE:
+ return pdf;
+ case PPCRYPT_PASS:
+ if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE ||
+ ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE)
+ return pdf;
+ printf("sorry, password needed\n");
+ ppdoc_free(pdf);
+ return NULL;
+ case PPCRYPT_FAIL:
+ printf("sorry, encryption failed\n");
+ ppdoc_free(pdf);
+ return NULL;
+ }
+
+[If you get ``PPCRYPT_FAIL`` it might mean *I failed*, so treat as a bug.]
+
+If you'd like to know what permissions are given/restricted to encrypted document::
+
+ ppint ppdoc_permissions (ppdoc *pdf);
+
+Returned value can be queried with the following binary flags (you can verify with Acrobat *File -> Properties -> Security* tab)::
+
+ PPDOC_ALLOW_PRINT // printing
+ PPDOC_ALLOW_MODIFY // filling form fields, signing, creating template pages
+ PPDOC_ALLOW_COPY // copying, copying for accessibility
+ PPDOC_ALLOW_ANNOTS // filling form fields, copying, signing
+ PPDOC_ALLOW_EXTRACT // contents copying for accessibility
+ PPDOC_ALLOW_ASSEMBLY // (no effect)
+ PPDOC_ALLOW_PRINT_HIRES // (no effect)
+
+``pplib`` does absolutelly nothing with permissions, it cares only to decrypt the document. As mentioned, encryption applies to strings
+and streams. ``pplib`` decrypt strings when parsing document objects, so the result you get is *normal* (not ciphered).
+Streams are decrypted whenever you access them. Even if you ask for a raw stream data, you'll get a raw (compressed) stream, but decrypted.
+So except the check to ``ppdoc_crypt_status()``, you shouldn't bother about encryption.
+
+In encrypted documents most of streams are encrypted. To check if a given stream is encrypted::
+
+ ppstream_encrypted(stream) // macro, returns non-zero if encrypted
+
+Encryption is independent from compression, don't confuse with ``ppstream_compressed()``
+
+Pages
+-----
+
+Several helpers to deal with pages. To get the number of pages::
+
+ ppuint ppdoc_page_count (ppdoc *pdf);
+
+To access the root pages tree node::
+
+ ppref * ppdoc_pages(ppdoc *pdf);
+
+To get the page reference at a given index::
+
+ ppref * ppdoc_page (ppdoc *pdf, ppuint index);
+
+``index`` is a page number. First page has number 1. For index out of bounds ``ppdoc_page()`` returns NULL.
+Iterating over pages using index from 1 to ``ppdoc_page_count()`` and calling ``ppdoc_page()`` on each iteration
+would be suboptimal. Here is a dedicted iterator for this::
+
+ ppref * ppdoc_first_page (ppdoc *pdf);
+ ppref * ppdoc_next_page (ppdoc *pdf);
+
+The iterator in use::
+
+ ppdoc *pdf;
+ ppref *ref;
+ ppdict *dict;
+ int pageno;
+
+ pdf = ppdoc_load("file.pdf");
+ for (ref = ppdoc_first_page(pdf), pageno = 1; ref != NULL; ref = ppdoc_next_page(pdf), ++pageno)
+ {
+ dict = ppref_obj(obj)->dict; // take for granted it is a dict
+ // do something with the page dict
+ }
+
+Functions related to pages return ``ppref *`` ensured to contain dict object, so you don't need sanity
+type checks here.
+
+Contents
+--------
+
+PDF page contents can be given as a stream or array of streams. Here is a convenience iterator over page
+contents streams::
+
+ ppstream * ppcontents_first (ppdict *dict);
+ ppstream * ppcontents_next (ppdict *dict, ppstream *stream);
+
+A complete example of contents stream parser use is given below (example 2).
+But before we get there, we need to introduce ``ppcontext`` object. Conceptually,
+``ppcontext`` is an owner (memory handler) of objects created on demand (beyond the ``ppdoc``).
+So far used only with contents stream parser, which might produce quite some data that we want
+to release just after used. To create a new context::
+
+ pcontext * ppcontext_new (void);
+
+It initializes a new context and its internal memory heap, taking about 64kB on start. After that,
+the context is ready to produce objects (contents parsing functions below). Once objects produced
+from a given context are no longer needed::
+
+ void ppcontext_done (ppcontext *context);
+
+It restores the context to its initial state, as after ``ppcontext_new()``. It means that the context
+is ready to produce another bunch of beings (in the example below, all objects from the next page contents).
+Once the context is not needed anymore::
+
+ void ppcontext_free (ppcontext *context);
+
+Now, contents stream parser functions take the context as an argument. Iterator form of contents stream parser
+that allows to process the contents operator by operator::
+
+ ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname);
+ ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname);
+
+Returned ``ppobj *`` is a pointer to operands list. ``*psize`` is the number of operands on stack.
+The operator itself is stored as ``*pname``.
+
+To parse the entire contents stream at once with no stop at every operator::
+
+ ppobj * ppcontents_parse (ppcontext *context, ppstream *stream, size_t *psize);
+
+Returns probably quite long list of all parsed objects (operands and operatos) in one piece.
+The number of objects is stored to ``*psize``.
+
+[Contents may contain so called inline images, that breaks a simple scheme of operands / operator syntax::
+
+ BI <keyval pairs> ID <binary image data> EI
+
+Contents parser treats this genuine triplet as a single piece, producing two operands (dict and string)
+followed by ``EI`` operator name.]
+
+Boxes
+-----
+
+Boxes (rectangles) in PDF are roughly 4-number arrays, but with a special intent.
+``pplib`` provides a basic interface for these special arrays::
+
+ typedef struct {
+ ppnum lx, ly, rx, ry;
+ } pprect;
+
+This type is used only by helper functions - PDF parser is not aware of the rectangle type.
+To convert ``pparray`` to ``pprect``::
+
+ pprect * pparray_to_rect (pparray *array, pprect *rect); // returns rect or NULL
+
+In example::
+
+ pprect rect;
+ if (pparray_to_rect(array, &rect) != NULL)
+ ; // do something with rect
+
+To get some image bounding box::
+
+ pprect * ppdict_get_rect (ppdict *dict, const char *name, pprect *rect);
+ // eg. ppdict_get_rect(imagedict, "BBox", &rect)
+
+To get some page box::
+
+ pprect * ppdict_get_box (ppdict *dict, const char *name, pprect *rect);
+ // eg. ppdict_get_box(pagedict, "MediaBox", &rect)
+
+The later not only checks the pagedict, but also goes through parent page nodes.
+
+Transforms
+----------
+
+Transformations are given as 6-number arrays, but with a special intent.
+``pplib`` provides a basic interface for these special arrays::
+
+ typedef struct {
+ ppnum xx, xy, yx, yy, x, y;
+ } ppmatrix;
+
+This type is used only by helper functions - PDF parser is not aware of the matrix type.
+To convert ``pparray`` to ``ppmatrix``::
+
+ ppmatrix * pparray_to_matrix (pparray *array, ppmatrix *matrix);
+
+In example::
+
+ ppmatrix matrix;
+ if (pparray_to_matrix(array, &matrix) != NULL)
+ ; // do something with matrix
+
+To get the matrix from dict::
+
+ ppmatrix * ppdict_get_matrix (ppdict *dict, const char *name, ppmatrix *matrix);
+ // eg. ppdict_get_matrix(imagedict, "Matrix", &matrix)
+
+Errors handling
+---------------
+
+``pplib`` is not verbose, but might happen that it needs to log some error message, eg. when parsing
+of some PDF boject fails due to invalid offsets. By default, ``pplib`` prints the message to stdout, eg.::
+
+ invalid 123 0 R object at offset 123123
+
+To replace the default logger, you can provide your own::
+
+ void pplog_callback (pplogger_callback logger, void *alien);
+
+``pplogger_callback`` is a function::
+
+ void your_callback (const char *message, void *alien);
+
+In example, to redirect messages to stderr you may define a function::
+
+ void your_callback (const char *message, void *alien)
+ {
+ fprintf((FILE *)alien, "\nooops: %s\n", message);
+ }
+
+Then set the callback somewhere before loading documents::
+
+ pplog_callback(your_callback, stderr);
+
+(example 2 uses that).
+
+To set the default log messages prefix, eg. ``pplib:``, use::
+
+ int pplog_prefix (const char *prefix)
+
+Default is empty. The function succeeds if provided prefix is reasonably short (less then 32 bytes).
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppapi-2.x.rst.txt b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppapi-2.x.rst.txt new file mode 100644 index 00000000000..250cd8fcd35 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppapi-2.x.rst.txt @@ -0,0 +1,937 @@ +
+``pplib`` 2.x
+=============
+
+``pplib`` is a library for raw PDF access. It parses PDF documents and provides an interface to access document structures in C.
+
+C-API
+=====
+
+Types
+-----
+
+``pplib`` defines several C-types to represent PDF types:
+
+- ``ppbyte`` - char
+- ``ppint`` - signed integer (``int64_t``)
+- ``ppnum`` - real number (double)
+- ``ppname`` - PDF name
+- ``ppstring`` - PDF string
+- ``pparray`` - PDF array
+- ``ppdict`` - PDF dict
+- ``ppstream`` - PDF stream
+- ``ppref`` - PDF indirect reference
+- ``ppobj`` - a container of all above
+
+Among ``ppint`` and ``ppnum``, we also use ``ppuint`` - unsigned integer (machine word, alias to ``size_t``).
+
+Other API types:
+
+- ``ppdoc`` - PDF document
+- ``ppxref`` - cross-references table
+- ``ppcontext`` - ... later
+- ``pprect`` - rectangle
+- ``ppmatrix`` - matrix
+
+Integer and number are as simple types. Names and strings used to be aliases to ``char *``
+in ``pplib 1.x``, now they are structures; all related API functions operate on pointers.
+Other types (array, dict, stream, reference, object container, xref, doc) are C-structures,
+and you operate it their pointers. So when you declare a simple type variable you say::
+
+ ppuint u;
+ ppnum n;
+ ...
+
+And when you declare a compound type you operate on pointers::
+
+ ppobj *obj;
+ ppname *name;
+ ppstring *string;
+ pparray *array;
+ ppdict *dict;
+ ppstream *stream;
+ ppref *ref;
+ ppdoc *pdf;
+
+Most of those C-types are defined in library header ``ppapi.h`` (complete types). Some others are incomplete
+(eg. you can't say ``sizeof(ppdoc)`` or ``sizeof(ppxref)``). This is to avoid unnecesary dependencies in
+the header. The library itself uses ``pplib.h`` header but for auxilary applications including a standalone
+``ppapi.h`` header should be enough.
+
+``pplib`` was designed having **read-only** PDF access in mind. Even if some structure is completelly exposed,
+so that you can directly access its members, you should treat them as read-only. I don't make them ``const`` because
+then all variable declarations would need to be ``const``, which is annoying, and I'd need some trickery in the library
+internals to unconst. Besides, nothing is really const for C type casts.
+
+Object
+------
+
+A common container for all elementary PDF object types is ``ppobj`` structure. ``ppobj`` has a type identifier
+(integer) and union of values::
+
+ struct ppobj {
+ ppobjtp type;
+ union {
+ ppint integer;
+ ppnum number;
+ ppname *name;
+ ppstring *string;
+ pparray *array;
+ ppdict *dict;
+ ppstream *stream;
+ ppref *ref;
+ void *any;
+ };
+ };
+
+Object type is one of constants (enum)::
+
+ PPNONE
+ PPNULL
+ PPBOOL
+ PPINT
+ PPNUM
+ PPNAME
+ PPSTRING
+ PPARRAY
+ PPDICT
+ PPSTREAM
+ PPREF
+
+The type determines the structure member you're allowed to access::
+
+ ppobj *obj;
+ ...
+ switch (obj->type)
+ {
+ case PPNONE: // shouldn't actually happen, indicates some failure
+ break;
+ case PPNULL: // valid PDF null object, no value
+ break;
+ case PPBOOL: // do something with obj->integer (ppint), value 0 or 1
+ break;
+ case PPINT: // do something with obj->integer (ppint)
+ break;
+ case PPNUM: // do something with obj->number (ppnum)
+ break;
+ case PPNAME: // do something with obj->name (ppname *)
+ break;
+ case PPSTRING: // do something with obj->string (ppstring *)
+ break;
+ case PPARRAY: // do something with obj->array (pparray *)
+ break;
+ case PPDICT: // do something with obj->dict (ppdict *)
+ break;
+ case PPSTREAM: // do something with obj->stream (ppstream *)
+ break;
+ case PPREF: // do something with obj->ref (ppref *)
+ break;
+ }
+
+More often then not you know exactly what type of object value is expected, in which case
+you may use one of the following macros::
+
+ // returns 1 if o->type is PPNULL
+ int ppobj_get_null(o) \
+
+ // if o->type is PPBOOL, sets int v to 0 or 1 and returns 1, 0 otherwise
+ int ppobj_get_bool(o, v)
+
+ // if o->type is PPINT, sets ppint v and returns 1, 0 otherwise
+ int ppobj_get_int(o, v)
+
+ // if o->type is PPINT and >= 0, sets ppuint v and returns 1, 0 otherwise
+ int ppobj_get_uint(o, v)
+
+ // if o->type is PPNUM or PPINT, sets ppnum v and returns 1, 0 otherwise
+ int ppobj_get_num(o, v)
+
+ // if o->type is PPNAME returns the name, NULL otherwise
+ ppname * ppobj_get_name(o)
+
+ // if o->type is PPSTRING returns the string, NULL otherwise
+ ppstring * ppobj_get_string(o)
+
+ // if o->type is PPARRAY returns the array, NULL otherwise
+ pparray * ppobj_get_array(o)
+
+ // if o->type is PPDICT returns the dict, NULL otherwise
+ ppdict * ppobj_get_dict(o)
+
+ // if o->type is PPSTREAM returns the stream, NULL otherwise
+ ppstream * ppobj_get_stream(o)
+
+ // if o->type is PPREF returns the reference, NULL otherwise
+ ppref * ppobj_get_ref(o)
+
+Note the coercion from integer to real number, but not reverse. In practise, whenever you expect a real number,
+you should also handle integer (eg. '1' used instead of '1.0' is pretty common in PDF).
+
+It is a common case that the object is given as an indirect reference, but what you actually
+want is not the reference, but the object referred by it. Here is a helper for it::
+
+ // if o->type is PPREF, returns what the reference points, otherwise returns o
+ ppobj * ppobj_rget_obj(o)
+
+Also every ``ppobj_get_*`` macro has ``ppobj_rget_*`` counterpart that makes a check
+for the expected type, but if the object is PPREF, it jumps to the target object.
+So for example ``ppobj_rget_dict(obj)`` will return dict if ``obj`` is of type PPDICT
+or if it is of type PPREF and ``obj->ref`` hosts an object of type PPDICT.
+
+Names
+-----
+
+PDF names are represented as ``ppname`` pointer (``ppname`` used to be an alias to ``char *``, now it is a structure).
+To access the name data::
+
+ ppbyte * ppname_data(name) // name->data, bytes array
+
+For convenient use in C, names are ``'\0'`` terminated. But to get the length of name better always use
+``ppname_size()`` macro. ``ppname`` object knows its size, don't use ``strlen()``::
+
+ size_t ppname_size(ppname name); // name->size, the length of name in bytes
+
+In current implementation names are not hashed anyhow, so name-to-name comparison is not smarter than ``memcmp()``.
+Use macros::
+
+ int ppname_is(ppname name, "literal"); // to compare ppname with C-literal string
+ int ppname_eq(ppname name, ppname other); // to compare ppname with a different name
+
+If you use ``pplib`` to parse contents streams, you may need to distinguish names from operators
+(more precisely executable names). Names in PDF are preceeded by '/', executable names aren't. In both
+cases PDF parser will produce ``ppname`` but the result can be distingushed with::
+
+ int ppname_exec(ppname name); // macro, returns non-zero if the name is executable
+
+Names are kept in their raw form, with possible PDF specific escapes (in text below we call it **encoded** form).
+Leading '/' is omitted. One may need a decoded name, with no PDF escapes.
+A pair of functions provides a simple interface to switch between those two forms::
+
+ // these helpers rely on name->alterego member
+ ppname * ppname_decoded (ppname *name); // returns decoded (unescaped) form of the name
+ ppname * ppname_encoded (ppname *name); // returns encoded (escaped) form of the name
+ ppbyte * ppname_decoded_data (ppname *name);
+ ppbyte * ppname_encoded_data (ppname *name);
+
+In pretty most cases a PDF name contains only letters (no special characters, no escapes), so decoded and encoded forms are identical.
+In that case both functions simply return the argument. It is ok to call ``ppname_decoded()`` on already decoded form
+and ``ppname_encoded()`` on already encoded form. Both forms are produced by PDF objects parser, so accessing ``ppname`` alter ego
+in whatever direction needs no extra decoding or allocation costs (the cost is paid by parser).
+
+String
+------
+
+PDF strings have the same internal construction as names, so most of names description above applies to strings as well.
+``ppstring`` is a structure (used to be an alias to ``char *``). ``string->data`` is ``\0``-terminated c-array of ``ppbytes``.
+To get the data::
+
+ ppbyte * ppstring_data(ppstring *string); // string->data, macro
+
+To get the size of the string::
+
+ size_t ppstring_size(ppstring *string); // macro, returns the length of the string in bytes
+
+Strings are provided in their raw form, preserving PDF specific escapes, but with no
+``()`` or ``<>`` delims. To distinguish plain strings from hex strings::
+
+ int ppstring_hex(ppstring string); // macro, returns non zero if hex string
+
+Or if you prefer::
+
+ switch (ppstring_type(string))
+ {
+ case PPSTRING_PLAIN: // literal string, surrounded by ``(`` and ``)`` in PDF
+ break;
+ case PPSTRING_BASE16: // hex string, surrounded by ``<`` and ``>`` in PDF
+ break;
+ case PPSTRING_BASE85: // base85 string surrounded by ``<~`` and ``~>`` in PDF
+ break;
+ }
+
+The last is actually Postscript specific, not used in PDF, but I think it might appear in contents streams...
+No matter how the string is given in PDF (plain or hex), here are two functions to
+switch between encoded and decoded strings forms::
+
+ ppstring * ppstring_decoded (ppstring *string); // returns decoded string possibly with PDF escapes
+ ppstring * ppstring_encoded (ppstring *string); // returns encoded string with no PDF escapes
+ ppbyte * ppstring_decoded_data (ppstring *string);
+ ppbyte * ppstring_encoded_data (ppstring *string);
+
+For hex strings, encoded form contains hex digits, while decoded form contains arbitrary bytes (the result of hex decoding).
+Plain strings usually contains printable ASCII characters, but they might contain any binary data.
+As with names, objects parser produces both forms. The raw form with PDF escapes (or raw hex form) the main one.
+Eg. when you access ``obj->string`` you always get the encoded form. At any moment you can switch to its alter ego.
+
+No matter if the string is plain or hex, if its first two bytes (decoded) are UTF16 BOM, the string is unicode.
+``ppstring`` object *knows* it is unicode or not::
+
+ switch (ppstring_utf(string))
+ {
+ case PPSTRING_UTF16LE: // unicode string, utf16le
+ break;
+ case PPSTRING_UTF16BE: // unicode string, utf16be
+ break;
+ default: // no unicode
+ }
+
+Or simply::
+
+ if (ppstring_utf(string) != 0) {
+ // handle unicode string
+ }
+
+If the string is unicode, BOM remains the part of the string -- ``pplib`` parser does not strip it.
+Unicode or not, encoded or decoded, strings are always C-arrays of bytes and ``ppstring_size()``
+always returns the size in bytes.
+
+Array
+-----
+
+PDF arrays are represented as ``pparray`` type, which is C-array of ``ppobj`` structures.
+To get the size::
+
+ size_t pparray_size(pparray *array) // macro, returns the number of array items
+
+To get ``ppobj *`` at a given index::
+
+ ppobj * pparray_at(array, index) // macro, returns ppobj * (no index check)
+ ppobj * pparray_get(array, index) // macro, returns ppobj * or NULL (with index check)
+ ppobj * pparray_get_obj (pparray *array, size_t index); // function equiv to pparray_get()
+
+Iterating over array elements::
+
+ pparray *array;
+ size_t index, size;
+ ppobj *obj;
+ for (size = pparray_size(array), pparray_first(array, index, obj); index < size; pparray_next(index, obj))
+ {
+ // do something with index and obj
+ }
+
+There is no magic first/next macros, just iteration over pointers. One could also use something like::
+
+ for (index = 0, size = array->size; index < size; ++index)
+ {
+ obj = pparray_at(array, index);
+ // do something with index and obj
+ }
+
+When getting values from array and expecting a result of known type, use one of the following::
+
+ int pparray_get_bool (pparray *array, size_t index, int *v); // get boolean value
+ int pparray_get_int (pparray *array, size_t index, ppint *v); // get ppint value
+ int pparray_get_uint (pparray *array, size_t index, ppuint *v); // get ppuint value
+ int pparray_get_num (pparray *array, size_t index, ppnum *v); // get ppnum value
+ ppname * pparray_get_name (pparray *array, size_t index); // get ppname * value
+ ppstring * pparray_get_string (pparray *array, size_t index); // get ppstring * value
+ pparray * pparray_get_array (pparray *array, size_t index); // get pparray * value
+ ppdict * pparray_get_dict (pparray *array, size_t index); // get ppdict * value
+ ppref * pparray_get_ref (pparray *array, size_t index); // get ppref * value
+
+As with ``ppobj_get_*`` suite, numeric types getters set the value of a given type and returns 1, if the type matches.
+Otherwise sets nothing and returns 0. Other getters return the value if the type matches, or NULL.
+
+Every function from ``pparray_get_*`` suite have its ``pparray_rget_*`` counterpart
+that dereferences indirect objects (as explained for ``ppobj_rget_*`` getters). Note that
+there is no ``pparray_get_stream()`` function, as streams in PDF are always indirect
+(may only reside in ``ref->object.stream``). To get the stream from array use::
+
+ ppstream * pparray_rget_stream (pparray *array, size_t index);
+
+Dict
+----
+
+PDF dicts are represented as ``ppdict`` structure, which is C-array of ``ppobj`` with parallel
+C-array of ``ppname`` pointers. To get the size of a dict::
+
+ size_t ppdict_size(ppdict *dict) // macro, returns the number of key-val pairs
+
+To get the value at a given index (integer)::
+
+ ppobj * ppdict_at(ppdict *dict, index) // macro, no index bounds check
+
+To get the name (key) at a given index::
+
+ ppname * ppdict_key(ppdict *dict, index) // macro, no index bounds check
+
+To iterate over dict key-val pairs::
+
+ ppdict *dict;
+ ppname **pkey;
+ ppobj *obj;
+
+ for (ppdict_first(dict, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj))
+ {
+ // do something with *pkey and obj
+ }
+
+There is no magic in first/next macros, just iteration through keys and values lists pointers.
+For convenient iteration, a list of keys is terminated with NULL, so in the code above ``*pkey != NULL``
+is used as the loop condition. One may also iterate via indices::
+
+ ppdict *dict;
+ size_t index, size;
+ ppname *key;
+ ppobj *obj;
+ for (index = 0, size = ppdict_size(dict); index < size; ++index)
+ {
+ key = ppdict_key(dict, index);
+ obj = ppdict_at(dict, index);
+ // do something with key and obj
+ }
+
+To get the object associated with a given name, use one of the following::
+
+ ppobj * ppdict_get_obj (ppdict *dict, const char *name);
+ int ppdict_get_bool (ppdict *dict, const char *name, int *v);
+ int ppdict_get_int (ppdict *dict, const char *name, ppint *v);
+ int ppdict_get_uint (ppdict *dict, const char *name, ppuint *v);
+ int ppdict_get_num (ppdict *dict, const char *name, ppnum *v);
+ ppname ppdict_get_name (ppdict *dict, const char *name);
+ ppstring ppdict_get_string (ppdict *dict, const char *name);
+ pparray * ppdict_get_array (ppdict *dict, const char *name);
+ ppdict * ppdict_get_dict (ppdict *dict, const char *name);
+ ppref * ppdict_get_ref (ppdict *dict, const char *name);
+
+Note that all getters accepts ``const char *`` as key, so it is ok to say::
+
+ ppdict_rget_dict(dict, "Resources");
+
+(the most common use I guess). But to use ``ppname`` object as a key, one have to
+use data member::
+
+ ppdic_rget_dict(dict, name->data); // ppname *name
+
+Every ``ppdict_get_*`` getter has ``ppdict_rget_*`` counterpart that dereferences
+indirect objects if necessary. Note that there is no ``ppdict_get_stream()`` function,
+but there is::
+
+ ppstream * ppdict_rget_stream (ppdict *dict, const char *name);
+
+So far dicts comes with no names mapping, so by-name dict accessors perform a linear search
+through the keys list. PDF dicts are usually small.
+
+Stream
+------
+
+PDF streams are represented as ``ppstream`` objects. To get the stream dict::
+
+ ppdict * ppstream_dict(ppstream *stream) // macro
+
+To read the stream data::
+
+ uint8_t * ppstream_first (ppstream *stream, size_t *size, int decode);
+ uint8_t * ppstream_next (ppstream *stream, size_t *size);
+ void ppstream_done (ppstream *stream);
+
+Both ``first` and ``next`` functions return a chunk of stream data and sets the ``size`` of the chunk.
+``decode`` parameter tell the reader to decompress the stream (1) or return raw (0). A call to ``ppstream_next()``
+must be preceeded by ``ppstream_first()``. Once you're done with the stream, you have to call ``ppstream_done()``,
+no matter if the stream has been read to the end or not. The stream data iterator in use::
+
+ uint8_t *data;
+ size_t size;
+ ppstream *stream;
+ int decode = 1; // 1 - get decompressed, 0 - get raw
+
+ for (data = ppstream_first(stream, &size, decode); data != NULL; data = ppstream_next(stream, &size))
+ {
+ // do something with data and its size
+ }
+ ppstream_done(stream);
+
+Every subsequent iterator call invalidates the previous reader output, so you have to utilize the returned chunk
+of data just after you ot that. So the following is wrong::
+
+ data1 = ppstream_first(stream, &size, 1);
+ data2 = ppstream_next(stream, &size);
+ data3 = ppstream_next(stream, &size);
+ some_output(data1, size);
+ some_output(data2, size);
+
+The reader calls usually return the same pointer to internal buffer, just filled with a different data.
+``pplib`` allocates reasonably large buffer and fills that buffer on subsequent calls to the reader.
+
+If the source stream has no compression, using both ``decode == 1`` and ``decode == 0`` should give the same result.
+You can check if the stream is actually compressed with::
+
+ ppstream_compressed(stream) // macro, returns non zero if /Filter is present
+
+It might be necessary to load the entire stream data at once::
+
+ uint8_t * ppstream_all (ppstream *stream, size_t *size, int decode);
+
+If the initial buffer size is insufficient, it grows until the entire stream data is loaded. You must call
+``ppstream_done(stream)`` after using returned data.
+
+``ppstream_done()`` doesn't invalidate the stream object, it just closes its internal reader.
+The stream itself remains a valid object (eg. one can read it again if necessary),
+but the reader buffer is released. It is actually not freed but kept for future the reuse with that on some other stream,
+but you still need to mark it ready for reuse to avoid allocating a separate buffer for every stream you're going to read.
+
+Stream data readers will return ``NULL`` if you haven't close the previous reader process with ``ppstream_done()``. All below is wrong::
+
+ data1 = ppstream_all(stream, &size, 1);
+ data2 = ppstream_all(stream, &size, 1); // data2 == NULL
+ // or
+ data1 = ppstream_first(stream, &size, 1);
+ data2 = ppstream_first(stream, &size, 1); // data2 == NULL
+ // or
+ data1 = ppstream_first(stream, &size, 1);
+ data2 = ppstream_all(stream, &size, 1); // data2 == NULL
+
+To avoid unnecessary dependencies, ``pplib`` does not support image filters (``/DCT``, ``/JPX``, ``/JBIG``, ``/CCITT``).
+But it is ok to read the stream with ``decode`` set to 1 on such streams. ``pplib`` assumes that the image is the
+final/target stream form and just returns it as-is. Eg. in the case of JPEG (``/DCT`` filtered) image both calls should
+give the same results::
+
+ ppstream_all(jpegstream, &jpegsize, 0); // don't decode, return what's there
+ ppstream_all(jpegstream, &jpegsize, 1); // decode but found image filter, effectively the same
+
+A bit more about streams memory. As mentioned, ``pplib`` allocates buffers for stream readers. After ``ppstream_done()``,
+the stream no longer *owns* the buffer space. But the buffer may remain allocated, to be reused with future readers.
+``pplib`` keeps a pool of several buffers. This means, that when you use stream readers, ``pplib`` eats
+some memory (1MB or so) that is not freed, even if no streams are used. And even if you free all objects.
+If you suffer from this, you can optionally use a pair of functions::
+
+ void ppstream_init_buffers (void);
+ void ppstream_free_buffers (void);
+
+The first initializes buffers pool, unless done so far. Currently ``pplib`` cares of it before opening every stream reader,
+so it is not obligatory. The second frees a pool of buffers. The intended use is to call ``ppstream_init_buffers()`` once
+as kind of library initializer and to call ``ppstream_free_buffers()`` once, as the library finalizer.
+
+Filters
+-------
+
+``ppstream`` knows its filter(s) and keps it as ``stream->filter``::
+
+ // ppstream *stream;
+ ppstream_filter *info = &stream->filter;
+
+``ppstream_filter`` is the following structure::
+
+ typedef struct {
+ ppstreamtp *filters; // c-array of filter identifiers (enum integers)
+ ppdict **params; // c-array of ppdict pointers
+ size_t count; // number of filters, length of the arrays (typically 1)
+ } ppstream_filter;
+
+If ``count > 0`` then ``filters`` member is not NULL. Filters array keeps integer constants::
+
+ PPSTREAM_BASE16 /* /ASCIIHexDecode */
+ PPSTREAM_BASE85 /* /ASCII85Decode */
+ PPSTREAM_RUNLENGTH /* /RunLengthDecode */
+ PPSTREAM_FLATE /* /FlateDecode */
+ PPSTREAM_LZW /* /LZWDecode */
+ PPSTREAM_CCITT /* /CCITTFaxDecode */
+ PPSTREAM_DCT /* /DCTDecode */
+ PPSTREAM_JBIG2 /* /JBIG2Decode */
+ PPSTREAM_JPX /* /JPXDecode */
+ PPSTREAM_CRYPT /* /Crypt */
+
+Params array keeps corresponding filter parameters (``/DecodeParms``) if present. ``params`` member is not NULL
+if ``count > 0`` and the stream dict has ``/DecodeParms`` entry. Even if ``params`` is there,
+for every N-th filter, ``params[N]`` may be NULL (corresponding to PDF ``null``).
+
+``stream->filter`` keeps the source stream filter information, which may not correspond to the result of stream readers
+(``ppstream_first()``, ``ppstream_next()``, ``ppstream_all()``). The get the filters info relevant to the result from readers::
+
+ void ppstream_filter_info (ppstream *stream, ppstream_filter *info, int decode);
+
+The function fills ``ppstream_filter`` structure according to the expected result from stream readers (example 3 shows
+how to use it to reconstruct ``/Filter`` and ``/DecodeParms`` when copying the stream to some other PDF).
+
+To convert filter identifier (``ppstreamtp``) to a corresponding PDF filter name::
+
+ const char * ppstream_filter_name[];
+
+To covert ``ppname`` to filter identifier::
+
+ int ppstream_filter_type (ppname filtername, ppstreamtp *filtertype);
+ // returns 1 and sets filtertype if filtername is the proper filter name
+
+Additional information about the stream can be fetched from macros::
+
+ ppstream_compressed(stream) /* stream->flags & (PPSTREAM_FILTER|PPSTREAM_IMAGE) */
+ ppstream_filtered(stream) /* stream->flags & PPSTREAM_FILTER */
+ ppstream_image(stream) /* stream->flags * PPSTREAM_IMAGE */
+
+``stream->flags`` is a binary sum of the following::
+
+ PPSTREAM_FILTER /* set iff the stream filters list has one of: BASE16, BASE85, RUNLENGTH, FLATE, LZW */
+ PPSTREAM_IMAGE /* set iff the stream filters list has one of: CCITT, DCT, JBIG2, JPX */
+ PPSTREAM_ENCRYPTED /* set iff the stream is encrypted */
+ PPSTREAM_ENCRYPTED_OWN /* set iff the stream has own CRYPT filter */
+
+Note that ``PPSTREAM_COMPRESSED`` is not there any longer, use ``ppstream_compressed()`` instead.
+And there is some more, see ``ppapi.h``.
+
+Ref
+---
+
+Indirect objects are represented as ``ppref`` structure. To get the object that the
+reference refers to::
+
+ ppobj * ppref_obj(ppref *ref) // macro
+
+``ppref`` structure also keeps the reference number and version, a pointer to cross reference table it belongs
+to and others, but I guess you won't need anything but the referenced object. ``pplib`` parser resolves references
+on-fly. So if there is a dict with indirect objects::
+
+ <<
+ /Type /Page
+ /Resources 123 0 R
+ ...
+ >>
+
+the parser will produce ``ppdict`` with ``Resources`` key pointing the proper ``ppref *`` value.
+If you need more, access ``ppref`` members::
+
+ struct ppref {
+ ppobj object; // target object
+ ppuint number, version; // identifiers
+ size_t offset; // file offset (useless for you, may be zero for compressed objects)
+ ppuint length; // the length of the original object data
+ ppxref *xref; // cross reference table it belongs to
+ };
+
+
+XRef
+----
+
+Cross reference table is exposed as ``ppxref`` (incomplete type, you can only oprate on its pointer).
+To get top document xref::
+
+ ppxref * ppdoc_xref (ppdoc *pdf);
+
+To get previous (older) xref::
+
+ ppxref * ppxref_prev (ppxref *xref);
+
+To find an object of a given refnumber::
+
+ ppref * ppxref_find (ppxref *xref, ppuint refnumber);
+
+[Note: since pplib v0.98 in case of documents with incremental update, ``ppxref_find()`` returns
+the newest available version of a given object rather than the object in a given body.]
+
+PDF
+---
+
+PDF document is represented as ``ppdoc`` structure (incomplete type, you can only operate on its pointer).
+To load a document from file::
+
+ ppdoc * ppdoc_load (const char *filename);
+
+To load a document from file handle::
+
+ ppdoc * ppdoc_filehandle (FILE *file, int closefile); // closefile 1 to fclose() on end
+
+To load a document from memory data::
+
+ ppdoc * ppdoc_mem (const void *data, size_t size);
+
+The data is assumed to be a buffer allocated with ``malloc`` - it is freed when destroying ``ppdoc``.
+
+Both loaders returns ``NULL`` on failure.
+
+To free ``ppdoc`` and all objects it refers to::
+
+ void ppdoc_free (ppdoc *pdf);
+
+So far we haven't mention about any explicit object reclaimers. There are no dedicated ``free`` functions
+for other objects. You don't allocate or free objects yourself. ``ppdoc`` object is an owner of all
+beings it refers to. It also means that every object described so far is alive as long as the containing
+``ppdoc`` is alive.
+
+To access main PDF dicts::
+
+ ppdict * ppdoc_trailer(ppdoc *pdf); // returns top xref trailer dict
+ ppdict * ppdoc_catalog(ppdoc *pdf); // returns catalog referred from the trailer
+ ppdict * ppdoc_info(ppdoc *pdf); // returns info dict referred from the trailer
+
+To get the PDF version::
+
+ const char * ppdoc_version_string (ppdoc *pdf); // version string
+ int ppdoc_version_number (ppdoc *pdf, int *minor); // minor and major numbers
+
+To get the file size of the source PDF document::
+
+ size_t ppdoc_file_size (ppdoc *pdf);
+
+To get the number of objects in all xrefs::
+
+ ppuint ppdoc_objects (ppdoc *pdf);
+
+To get the approx usage of memory::
+
+ size_t ppdoc_memory (ppdoc *pdf, size_t *waste);
+
+Encryption
+----------
+
+``pplib`` handles encrypted (password protected) documents. If a document is encrypted, most of strings and streams are ciphered.
+In that form they are unreadable and rather useless, you can't even rewrite such strings/streams as-is to a different PDF output.
+It is a common practise to *protect* documents with an empty password. Such documents remain readable in Acrobat (just opens them without prompting
+for a password), but some features (eg. printing) may restricted by the application.
+
+When ``pplib`` detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, ``pplib`` proceeeds normally, providing
+an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, ``pplib`` gives
+a way to provide a password and proceed. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object wntries
+set to ``null``.
+
+After loading a document you should check encryption status with::
+
+ ppcrypt_status ppdoc_crypt_status (ppdoc *pdf);
+
+``ppcrypt_status`` (integer) may have the following values:
+
+ ``PPCRYPT_NONE`` - no encryption, go ahead
+ ``PPCRYPT_DONE`` - encryption present but password succeeded, go ahead
+ ``PPCRYPT_PASS`` - encryption present, need non-empty password
+ ``PPCRYPT_FAIL`` - invalid or unsupported encryption (eg. undocumented in pdf spec)
+
+If a password is needed, you can provide one with::
+
+ ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength,
+ const void *ownerpass, size_t ownerpasslength);
+
+Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough
+to know that having one of them is enough to decrypt the document. If you know the password, you probably mean
+``userpass``, in which case you should put ``NULL`` as ``ownerpass``. The function returns ``PPCRYPT_DONE`` if the password
+succeeds and the previous status otherwise. Your custom loader function may look like that::
+
+ ppdoc *pdf;
+ pdf = ppdoc_load("file.pdf");
+ if (pdf == NULL)
+ return NULL;
+ switch (ppdoc_crypt_status(pdf))
+ {
+ case PPCRYPT_NONE:
+ case PPCRYPT_DONE:
+ return pdf;
+ case PPCRYPT_PASS:
+ if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE ||
+ ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE)
+ return pdf;
+ printf("sorry, password needed\n");
+ ppdoc_free(pdf);
+ return NULL;
+ case PPCRYPT_FAIL:
+ printf("sorry, encryption failed\n");
+ ppdoc_free(pdf);
+ return NULL;
+ }
+
+[If you get ``PPCRYPT_FAIL`` it might mean *I failed*, so treat as a bug.]
+
+If you'd like to know what permissions are given/restricted to encrypted document::
+
+ ppint ppdoc_permissions (ppdoc *pdf);
+
+Returned value can be queried with the following binary flags (you can verify with Acrobat *File -> Properties -> Security* tab)::
+
+ PPDOC_ALLOW_PRINT // printing
+ PPDOC_ALLOW_MODIFY // filling form fields, signing, creating template pages
+ PPDOC_ALLOW_COPY // copying, copying for accessibility
+ PPDOC_ALLOW_ANNOTS // filling form fields, copying, signing
+ PPDOC_ALLOW_EXTRACT // contents copying for accessibility
+ PPDOC_ALLOW_ASSEMBLY // (no effect)
+ PPDOC_ALLOW_PRINT_HIRES // (no effect)
+
+``pplib`` does absolutelly nothing with permissions, it cares only to decrypt the document. As mentioned, encryption applies to strings
+and streams. ``pplib`` decrypt strings when parsing document objects, so the result you get is *normal* (not ciphered).
+Streams are decrypted whenever you access them. Even if you ask for a raw stream data, you'll get a raw (compressed) stream, but decrypted.
+So except the check to ``ppdoc_crypt_status()``, you shouldn't bother about encryption.
+
+In encrypted documents most of streams are encrypted. To check if a given stream is encrypted::
+
+ ppstream_encrypted(stream) // macro, returns non-zero if encrypted
+
+Encryption is independent from compression, don't confuse with ``ppstream_compressed()``
+
+Pages
+-----
+
+Several helpers to deal with pages. To get the number of pages::
+
+ ppuint ppdoc_page_count (ppdoc *pdf);
+
+To access the root pages tree node::
+
+ ppref * ppdoc_pages(ppdoc *pdf);
+
+To get the page reference at a given index::
+
+ ppref * ppdoc_page (ppdoc *pdf, ppuint index);
+
+``index`` is a page number. First page has number 1. For index out of bounds ``ppdoc_page()`` returns NULL.
+Iterating over pages using index from 1 to ``ppdoc_page_count()`` and calling ``ppdoc_page()`` on each iteration
+would be suboptimal. Here is a dedicted iterator for this::
+
+ ppref * ppdoc_first_page (ppdoc *pdf);
+ ppref * ppdoc_next_page (ppdoc *pdf);
+
+The iterator in use::
+
+ ppdoc *pdf;
+ ppref *ref;
+ ppdict *dict;
+ int pageno;
+
+ pdf = ppdoc_load("file.pdf");
+ for (ref = ppdoc_first_page(pdf), pageno = 1; ref != NULL; ref = ppdoc_next_page(pdf), ++pageno)
+ {
+ dict = ppref_obj(obj)->dict; // take for granted it is a dict
+ // do something with the page dict
+ }
+
+Functions related to pages return ``ppref *`` ensured to contain dict object, so you don't need sanity
+type checks here.
+
+Contents
+--------
+
+PDF page contents can be given as a stream or array of streams. Here is a convenience iterator over page
+contents streams::
+
+ ppstream * ppcontents_first (ppdict *dict);
+ ppstream * ppcontents_next (ppdict *dict, ppstream *stream);
+
+A complete example of contents stream parser use is given below (example 2).
+But before we get there, we need to introduce ``ppcontext`` object. Conceptually,
+``ppcontext`` is an owner (memory handler) of objects created on demand (beyond the ``ppdoc``).
+So far used only with contents stream parser, which might produce quite some data that we want
+to release just after used. To create a new context::
+
+ pcontext * ppcontext_new (void);
+
+It initializes a new context and its internal memory heap, taking about 64kB on start. After that,
+the context is ready to produce objects (contents parsing functions below). Once objects produced
+from a given context are no longer needed::
+
+ void ppcontext_done (ppcontext *context);
+
+It restores the context to its initial state, as after ``ppcontext_new()``. It means that the context
+is ready to produce another bunch of beings (in the example below, all objects from the next page contents).
+Once the context is not needed anymore::
+
+ void ppcontext_free (ppcontext *context);
+
+Now, contents stream parser functions take the context as an argument. Iterator form of contents stream parser
+that allows to process the contents operator by operator::
+
+ ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname);
+ ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname);
+
+Returned ``ppobj *`` is a pointer to operands list. ``*psize`` is the number of operands on stack.
+The operator itself is stored as ``*pname``.
+
+To parse the entire contents stream at once with no stop at every operator::
+
+ ppobj * ppcontents_parse (ppcontext *context, ppstream *stream, size_t *psize);
+
+Returns probably quite long list of all parsed objects (operands and operatos) in one piece.
+The number of objects is stored to ``*psize``.
+
+[Contents may contain so called inline images, that breaks a simple scheme of operands / operator syntax::
+
+ BI <keyval pairs> ID <binary image data> EI
+
+Contents parser treats this genuine triplet as a single piece, producing two operands (dict and string)
+followed by ``EI`` operator name.]
+
+Boxes
+-----
+
+Boxes (rectangles) in PDF are roughly 4-number arrays, but with a special intent.
+``pplib`` provides a basic interface for these special arrays::
+
+ typedef struct {
+ ppnum lx, ly, rx, ry;
+ } pprect;
+
+This type is used only by helper functions - PDF parser is not aware of the rectangle type.
+To convert ``pparray`` to ``pprect``::
+
+ pprect * pparray_to_rect (pparray *array, pprect *rect); // returns rect or NULL
+
+In example::
+
+ pprect rect;
+ if (pparray_to_rect(array, &rect) != NULL)
+ ; // do something with rect
+
+To get some image bounding box::
+
+ pprect * ppdict_get_rect (ppdict *dict, const char *name, pprect *rect);
+ // eg. ppdict_get_rect(imagedict, "BBox", &rect)
+
+To get some page box::
+
+ pprect * ppdict_get_box (ppdict *dict, const char *name, pprect *rect);
+ // eg. ppdict_get_box(pagedict, "MediaBox", &rect)
+
+The later not only checks the pagedict, but also goes through parent page nodes.
+
+Transforms
+----------
+
+Transformations are given as 6-number arrays, but with a special intent.
+``pplib`` provides a basic interface for these special arrays::
+
+ typedef struct {
+ ppnum xx, xy, yx, yy, x, y;
+ } ppmatrix;
+
+This type is used only by helper functions - PDF parser is not aware of the matrix type.
+To convert ``pparray`` to ``ppmatrix``::
+
+ ppmatrix * pparray_to_matrix (pparray *array, ppmatrix *matrix);
+
+In example::
+
+ ppmatrix matrix;
+ if (pparray_to_matrix(array, &matrix) != NULL)
+ ; // do something with matrix
+
+To get the matrix from dict::
+
+ ppmatrix * ppdict_get_matrix (ppdict *dict, const char *name, ppmatrix *matrix);
+ // eg. ppdict_get_matrix(imagedict, "Matrix", &matrix)
+
+Errors handling
+---------------
+
+``pplib`` is not verbose, but might happen that it needs to log some error message, eg. when parsing
+of some PDF boject fails due to invalid offsets. By default, ``pplib`` prints the message to stdout, eg.::
+
+ invalid 123 0 R object at offset 123123
+
+To replace the default logger, you can provide your own::
+
+ void pplog_callback (pplogger_callback logger, void *alien);
+
+``pplogger_callback`` is a function::
+
+ void your_callback (const char *message, void *alien);
+
+In example, to redirect messages to stderr you may define a function::
+
+ void your_callback (const char *message, void *alien)
+ {
+ fprintf((FILE *)alien, "\nooops: %s\n", message);
+ }
+
+Then set the callback somewhere before loading documents::
+
+ pplog_callback(your_callback, stderr);
+
+(example 2 uses that).
+
+To set the default log messages prefix, eg. ``pplib:``, use::
+
+ int pplog_prefix (const char *prefix)
+
+Default is empty. The function succeeds if provided prefix is reasonably short (less then 32 bytes).
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_sources/ppapi.rst.txt b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppapi.rst.txt index 83a5b0fc370..5d1d2883e57 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_sources/ppapi.rst.txt +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppapi.rst.txt @@ -1,937 +1,937 @@ -
-``pplib``
-=========
-
-``pplib`` is a library for raw PDF access. It parses PDF documents and provides an interface to access document structures in C.
-
-C-API
-=====
-
-Types
------
-
-``pplib`` defines several C-types to represent PDF types:
-
-- ``ppint`` - signed integer (``int64_t``)
-- ``ppnum`` - real number (double)
-- ``ppname`` - PDF name
-- ``ppstring`` - PDF string
-- ``pparray`` - PDF array
-- ``ppdict`` - PDF dict
-- ``ppstream`` - PDF stream
-- ``ppref`` - PDF indirect reference
-- ``ppobj`` - a container of all above
-
-Among ``ppint`` and ``ppnum``, we also use ``ppuint`` - unsigned integer (machine word, alias to ``size_t``).
-
-Other API types:
-
-- ``ppdoc`` - PDF document
-- ``ppxref`` - cross-references table
-- ``ppcontext`` - ... later
-- ``pprect`` - rectangle
-- ``ppmatrix`` - matrix
-
-Integer, number, name and string are treated as simple types.
-Names and strings are actually C-structures, but exposed to API as typedefs to ``const char *``.
-Other types (array, dict, stream, reference, object container, xref, PDF) are C-structures,
-and you operate it their pointers. So when you declare a simple type variable you say::
-
- ppuint u;
- ppnum n;
- ppname name;
- ppstring string;
- ...
-
-And when you declare a compound type you operate on pointers::
-
- ppobj *obj;
- pparray *array;
- ppdict *dict;
- ppstream *stream;
- ppref *ref;
- ppdoc *pdf;
-
-Some of those C-types are defined in library header ``ppapi.h`` (complete types). Some others are incomplete
-(eg. you can't say ``sizeof(ppdoc)`` or ``sizeof(ppxref)``). This is to avoid unnecesary dependencies in
-the header. [At some points it's not clear to me what to hide and what to expose, will see.] The library itself
-uses ``pplib.h`` but for auxilary applications including a standalone ``ppapi.h`` header should be enough.
-
-``pplib`` was designed having **read-only** PDF access in mind. Even if some structure is completelly exposed,
-so that you can directly access its members, you should treat them as read-only. I don't make them ``const`` because
-then all variable declarations would need to be ``const``, which is annoying, and I'd need some trickery in the library
-internals to unconst. Besides, nothing is really const for C type casts.
-
-Object
-------
-
-A common container for all elementary PDF object types is ``ppobj`` structure. ``ppobj`` has a type identifier
-(integer) and union of values::
-
- struct ppobj {
- ppobjtp type;
- union {
- ppint integer;
- ppnum number;
- ppname name;
- ppstring string;
- pparray *array;
- ppdict *dict;
- ppstream *stream;
- ppref *ref;
- void *any;
- };
- };
-
-Object type is one of constants (enum)::
-
- PPNONE
- PPNULL
- PPBOOL
- PPINT
- PPNUM
- PPNAME
- PPSTRING
- PPARRAY
- PPDICT
- PPSTREAM
- PPREF
-
-The type determines the structure member you're allowed to access::
-
- ppobj *obj;
- ...
- switch (obj->type)
- {
- case PPNONE: // shouldn't actually happen, indicates some failure
- break;
- case PPNULL: // valid PDF null object, no value
- break;
- case PPBOOL: // do something with obj->integer (ppint), value 0 or 1
- break;
- case PPINT: // do something with obj->integer (ppint)
- break;
- case PPNUM: // do something with obj->number (ppnum)
- break;
- case PPNAME: // do something with obj->name (ppname)
- break;
- case PPSTRING: // do something with obj->string (ppstring)
- break;
- case PPARRAY: // do something with obj->array (pparray *)
- break;
- case PPDICT: // do something with obj->dict (ppdict *)
- break;
- case PPSTREAM: // do something with obj->stream (ppstream *)
- break;
- case PPREF: // do something with obj->ref (ppref *)
- break;
- }
-
-More often then not you know exactly what type of object value is expected, in which case
-you may use one of the following macros::
-
- // returns 1 if o->type is PPNULL
- int ppobj_get_null(o) \
-
- // if o->type is PPBOOL, sets int v to 0 or 1 and returns 1, 0 otherwise
- int ppobj_get_bool(o, v)
-
- // if o->type is PPINT, sets ppint v and returns 1, 0 otherwise
- int ppobj_get_int(o, v)
-
- // if o->type is PPINT and >= 0, sets ppuint v and returns 1, 0 otherwise
- int ppobj_get_uint(o, v)
-
- // if o->type is PPNUM or PPINT, sets ppnum v and returns 1, 0 otherwise
- int ppobj_get_num(o, v)
-
- // if o->type is PPNAME returns the name, NULL otherwise
- ppname ppobj_get_name(o)
-
- // if o->type is PPSTRING returns the string, NULL otherwise
- ppstring ppobj_get_string(o)
-
- // if o->type is PPARRAY returns the array, NULL otherwise
- pparray * ppobj_get_array(o)
-
- // if o->type is PPDICT returns the dict, NULL otherwise
- ppdict * ppobj_get_dict(o)
-
- // if o->type is PPSTREAM returns the stream, NULL otherwise
- ppstream * ppobj_get_stream(o)
-
- // if o->type is PPREF returns the reference, NULL otherwise
- ppref * ppobj_get_ref(o)
-
-Note the coercion from integer to real number, but not reverse. In practise, whenever you expect a real number,
-you should also handle integer (eg. '1' used instead of '1.0').
-
-It is a common case that the object is given as an indirect reference, but what you actually
-want is not the reference, but the object referred by it. Here is a helper for it::
-
- // if o->type is PPREF, returns what the reference points, otherwise returns o
- ppobj * ppobj_rget_obj(o)
-
-Also every ``ppobj_get_*`` macro has ``ppobj_rget_*`` counterpart that makes a check
-for the expected type, but if the object is PPREF, it jumps to the target object.
-So for example ``ppobj_rget_dict(obj)`` will return dict if ``obj`` is of type PPDICT
-or if it is of type PPREF and ``obj->ref`` hosts an object of type PPDICT.
-
-Names
------
-
-PDF names are represented as ``ppname``.
-I find it convenient to have ``ppname`` type pretending ``const char *``. This allows to use ``ppname``
-in all C-style string functions like ``printf("%s", name)``.
-
-Be aware, however, that ``ppname`` is actually a C-structure. It is perfectly ok to cast ``ppname`` to ``const char *``::
-
- ppname name;
- ...
- (const char *)name;
-
-But reverse is forbidden::
-
- const char *cstr = "cstring";
- ...
- (ppname)cstr; // expect segmentation fault soon
-
-For convenient use in C, names are ``'\0'`` terminated. But to get the length of name better always use
-``ppname_size()`` macro. ``ppname`` object knows its size, don't use ``strlen()``::
-
- size_t ppname_size(ppname name); // macro, returns length of name in bytes
-
-In current implementation names are not hashed anyhow, so name-to-name comparison is not smarter than ``memcmp()``.
-Use macros::
-
- int ppname_is(ppname name, "literal"); // to compare ppname with C-literal string
- int ppname_eq(ppname name, ppname other); // to compare ppname with a different name
-
-If you'll use ``pplib`` to parse contents streams, you may need to distinguish names from operators
-(more precisely executable names). Names in PDF are preceeded by '/', executable names aren't. In both
-cases PDF parser will produce ``ppname`` but can be distingushed with::
-
- int ppname_exec(ppname name); // returns non-zero if name is executable
-
-Names are kept in their raw form, with possible PDF specific escapes (in text below we call it **encoded** form).
-Leading '/' is omitted, though. One may need a decoded name, with no PDF escapes.
-A pair of functions provides a simple interface to switch between those two forms::
-
- ppname ppname_decoded (ppname name); // returns decoded (unescaped) form of the name
- ppname ppname_encoded (ppname name); // returns encoded (escaped) form of the name
-
-In pretty most cases PDF names contains only letters (no special characters, no escapes), so decoded and encoded forms are identical.
-In that case both functions simply return the argument. It is ok to call ``ppname_decoded()`` on already decoded form
-and ``ppname_encoded()`` on already encoded form. Both forms are produced by PDF objects parser, so accessing ``ppname`` alter ego
-in whatever direction needs no extra decoding or allocation costs.
-
-String
-------
-
-PDF strings have the same internal construction as names, so most of names description above applies to strings as well.
-``ppstring`` is a typedef of ``const char *``, roughly ``'\0'`` terminiated C-string. To get the size of the string::
-
- size_t ppstring_size(ppstring string); // macro, returns the length of the string in bytes
-
-Strings are provided in their raw form, preserving PDF specific escapes, but with no
-``()`` or ``<>`` delims. To distinguish plain strings from hex strings::
-
- int ppstring_hex(ppstring string); // macro, returns non zero if hex string
-
-Or if you prefer::
-
- switch (ppstring_type(string))
- {
- case PPSTRING_PLAIN: // literal string, surrounded by ``(`` and ``)`` in PDF
- break;
- case PPSTRING_BASE16: // hex string, surrounded by ``<`` and ``>`` in PDF
- break;
- case PPSTRING_BASE85: // base85 string surrounded by ``<~`` and ``~>`` in PDF
- break;
- }
-
-The last is actually Postscript specific, not used in PDF, but I think it might appear in contents streams...
-No matter how the string is given in PDF (plain or hex), here are two functions to
-switch between encoded and decoded strings forms::
-
- ppstring ppstring_decoded (ppstring string); // returns decoded string possibly with PDF escapes
- ppstring ppstring_encoded (ppstring string); // returns encoded string with no PDF escapes
-
-For hex strings, encoded form contains hex digits, while decoded form contains arbitrary bytes (the result of hex decoding).
-Plain strings usually contains printable ASCII characters, but they might contain any binary data.
-As with names, objects parser produces both forms. The raw form with PDF escapes (or raw hex form) is considered the main one.
-Eg. when you access ``obj->string`` you always get the encoded form. At any moment you can switch to its alter ego.
-
-No matter if the string is plain or hex, if its first two bytes (decoded) are UTF16 BOM, the string
-is considered unicode. ``ppstring`` object *knows* it is unicode or not::
-
- switch (ppstring_utf(string))
- {
- case PPSTRING_UTF16LE: // unicode string, utf16le
- break;
- case PPSTRING_UTF16BE: // unicode string, utf16be
- break;
- default: // no unicode
- }
-
-Or simply::
-
- if (ppstring_utf(string) != 0) {
- // handle unicode string
- }
-
-If the string is unicode, BOM remains the part of the string -- ``pplib`` parser does not strip it.
-Unicode or not, encoded or decoded, strings are always C-arrays of bytes and ``ppstring_size()``
-always returns the size in bytes.
-
-Array
------
-
-PDF arrays are represented as ``pparray`` type, which is C-array of ``ppobj`` structures.
-To get the size::
-
- size_t pparray_size(pparray *array) // macro, returns the number of array items
-
-To get ``ppobj *`` at a given index::
-
- ppobj * pparray_at(array, index) // macro, returns ppobj * (no index check)
- ppobj * pparray_get(array, index) // macro, returns ppobj * or NULL (with index check)
- ppobj * pparray_get_obj (pparray *array, size_t index); // function equiv to pparray_get()
-
-Iterating over array elements::
-
- pparray *array;
- size_t index, size;
- ppobj *obj;
- for (size = pparray_size(array), pparray_first(array, index, obj); index < size; pparray_next(index, obj))
- {
- // do something with index and obj
- }
-
-There is no magic first/next macros, just iteration over pointers. One could also use something like::
-
- for (index = 0, size = array->size; index < size; ++index)
- {
- obj = pparray_at(array, index);
- // do something with index and obj
- }
-
-When getting values from array and expecting a result of known type, use one of the following::
-
- int pparray_get_bool (pparray *array, size_t index, int *v); // get boolean value
- int pparray_get_int (pparray *array, size_t index, ppint *v); // get ppint value
- int pparray_get_uint (pparray *array, size_t index, ppuint *v); // get ppuint value
- int pparray_get_num (pparray *array, size_t index, ppnum *v); // get ppnum value
- ppname pparray_get_name (pparray *array, size_t index); // get ppname value
- ppstring pparray_get_string (pparray *array, size_t index); // get ppstring value
- pparray * pparray_get_array (pparray *array, size_t index); // get pparray * value
- ppdict * pparray_get_dict (pparray *array, size_t index); // get ppdict * value
- ppref * pparray_get_ref (pparray *array, size_t index); // get ppref * value
-
-As with ``ppobj_get_*`` suite, numeric types getters set the value of a given type and returns 1, if the type matches.
-Otherwise sets nothing and returns 0. Other getters return the value if the type matches, or NULL.
-
-Every function from ``pparray_get_*`` suite have its ``pparray_rget_*`` counterpart that
-that dereferences indirect objects (as explained for ``ppobj_rget_*`` getters). Note that
-there is no ``pparray_get_stream()`` function, as streams in PDF are always indirect.
-To get the stream from array use::
-
- ppstream * pparray_rget_stream (pparray *array, size_t index);
-
-Dict
-----
-
-PDF dicts are represented as ``ppdict`` structure, which is C-array of ``ppobj`` with parallel
-C-array of ``ppname`` pointers. To get the size of a dict::
-
- size_t ppdict_size(ppdict *dict) // macro, returns the number of key-val pairs
-
-To get the value at a given index (integer)::
-
- ppobj * ppdict_at(ppdict *dict, index) // macro, no index check
-
-To get the name (key) at a given index::
-
- ppname ppdict_key(ppdict *dict, index) // macro, no index check
-
-To iterate over dict key-val pairs::
-
- ppdict *dict;
- ppname *pkey;
- ppobj *obj;
-
- for (ppdict_first(dict, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj))
- {
- // do something with *pkey and obj
- }
-
-There is no magic in first/next macros, just iteration through keys and values lists pointers.
-For convenient iteration, a list of keys is terminated with NULL, so in the code above ``*pkey != NULL``
-is used as the loop condition. One may also iterate via indices::
-
- ppdict *dict;
- size_t index, size;
- ppname key;
- ppobj *obj;
- for (index = 0, size = ppdict_size(dict); index < size; ++index)
- {
- key = ppdict_key(dict, index);
- obj = ppdict_at(dict, index);
- // do something with key and obj
- }
-
-To get the object associated with a given name, use one of the following::
-
- ppobj * ppdict_get_obj (ppdict *dict, const char *name);
- int ppdict_get_bool (ppdict *dict, const char *name, int *v);
- int ppdict_get_int (ppdict *dict, const char *name, ppint *v);
- int ppdict_get_uint (ppdict *dict, const char *name, ppuint *v);
- int ppdict_get_num (ppdict *dict, const char *name, ppnum *v);
- ppname ppdict_get_name (ppdict *dict, const char *name);
- ppstring ppdict_get_string (ppdict *dict, const char *name);
- pparray * ppdict_get_array (ppdict *dict, const char *name);
- ppdict * ppdict_get_dict (ppdict *dict, const char *name);
- ppref * ppdict_get_ref (ppdict *dict, const char *name);
-
-Note that all getters accepts ``const char *`` as key, so it is ok to say::
-
- ppdict_rget_dict(dict, "Resources");
-
-as well as::
-
- ppdic_rget_dict(dict, name); // ppname name
-
-Every ``ppdict_get_*`` getter has ``ppdict_rget_*`` counterpart that dereferences
-indirect objects if necessary. Note that there is no ``ppdict_get_stream()`` function,
-but there is::
-
- ppstream * ppdict_rget_stream (ppdict *dict, const char *name);
-
-So far dicts comes with no names mapping, so by-name dict accessors perform a linear search
-through the keys list. PDF dicts are usually small, so it is fast enough.
-Building names lookup for every dict in PDF makes no sense I think, as ``pplib`` applications
-will query just several dicts I guess.. However, some apps may extensively query
-resources, which may refer to hundreds of objects (eg. images). So some mapping for dicts
-is still considered.
-
-Stream
-------
-
-PDF streams are represented as ``ppstream`` objects. To get the stream dict::
-
- ppdict * ppstream_dict(ppstream *stream) // macro
-
-To read the stream data::
-
- uint8_t * ppstream_first (ppstream *stream, size_t *size, int decode);
- uint8_t * ppstream_next (ppstream *stream, size_t *size);
- void ppstream_done (ppstream *stream);
-
-Both ``first` and ``next`` functions return a chunk of stream data and sets the ``size`` of the chunk.
-``decode`` parameter tell the reader to decompress the stream (1) or return raw (0). A call to ``ppstream_next()``
-must be preceeded by ``ppstream_first()``. Once you're done with the stream, you have to call ``ppstream_done()``,
-no matter if the stream has been read to the end or not. The stream data iterator in use::
-
- uint8_t *data;
- size_t size;
- ppstream *stream;
- int decode = 1; // 1 - get decompressed, 0 - get raw
-
- for (data = ppstream_first(stream, &size, decode); data != NULL; data = ppstream_next(stream, &size))
- {
- // do something with data and its size
- }
- ppstream_done(stream);
-
-Every subsequent iterator call invalidates the previous reader output, so you have to utilize the returned chunk
-of data just after you ot that. So the following is wrong::
-
- data1 = ppstream_first(stream, &size, 1);
- data2 = ppstream_next(stream, &size);
- data3 = ppstream_next(stream, &size);
- some_output(data1, size);
- some_output(data2, size);
-
-The reader calls usually return the same pointer to internal buffer, just filled with a different data.
-``pplib`` allocates reasonably large buffer and fills that buffer on subsequent calls to the reader.
-
-If the source stream has no compression, using both ``decode == 1`` and ``decode == 0`` should give the same result.
-You can check if the stream is actually compressed with::
-
- ppstream_compressed(stream) // macro, returns non zero if /Filter is present
-
-It might be necessary to load the entire stream data at once::
-
- uint8_t * ppstream_all (ppstream *stream, size_t *size, int decode);
-
-If the initial buffer size is insufficient, it grows until the entire stream data is loaded. You must call
-``ppstream_done(stream)`` after using returned data.
-
-``ppstream_done()`` doesn't invalidate the stream object, it just closes its internal reader.
-The stream itself remains a valid object (eg. one can read it again if necessary),
-but the reader buffer is released. It is actually not freed but kept for future the reuse with that on some other stream,
-but you still need to mark it ready for reuse to avoid allocating a separate buffer for every stream you're going to read.
-
-Stream data readers will return ``NULL`` if you haven't close the previous reader process with ``ppstream_done()``. All below is wrong::
-
- data1 = ppstream_all(stream, &size, 1);
- data2 = ppstream_all(stream, &size, 1); // data2 == NULL
- // or
- data1 = ppstream_first(stream, &size, 1);
- data2 = ppstream_first(stream, &size, 1); // data2 == NULL
- // or
- data1 = ppstream_first(stream, &size, 1);
- data2 = ppstream_all(stream, &size, 1); // data2 == NULL
-
-To avoid unnecessary dependencies, ``pplib`` does not support image filters (``/DCT``, ``/JPX``, ``/JBIG``, ``/CCITT``).
-But it is ok to read the stream with ``decode`` set to 1 on such streams. ``pplib`` assumes that the image is the
-final/target stream form and just returns it as-is. Eg. in the case of JPEG (``/DCT`` filtered) image both calls should
-give the same results::
-
- ppstream_all(jpegstream, &jpegsize, 0); // don't decode, return what's there
- ppstream_all(jpegstream, &jpegsize, 1); // decode but found image filter, effectively the same
-
-A bit more about streams memory. As mentioned, ``pplib`` allocates buffers for stream readers. After ``ppstream_done()``,
-the stream no longer *owns* the buffer space. But the buffer may remain allocated, to be reused with future readers.
-``pplib`` keeps a pool of several buffers. This means, that when you use stream readers, ``pplib`` eats
-some memory (1MB or so) that is not freed, even if no streams are used. And even if you free all objects.
-If you suffer from this, you can optionally use a pair of functions::
-
- void ppstream_init_buffers (void);
- void ppstream_free_buffers (void);
-
-The first initializes buffers pool, unless done so far. Currently ``pplib`` cares of it before opening every stream reader,
-so it is not obligatory. The second frees a pool of buffers. The intended use is to call ``ppstream_init_buffers()`` once
-as kind of library initializer and to call ``ppstream_free_buffers()`` once, as the library finalizer.
-
-Filters
--------
-
-In version v1.00 (20190916) ``ppstream`` API has been extended with filters information.
-``ppstream`` knows its filter(s) and keps it as ``stream->filter``::
-
- // ppstream *stream;
- ppstream_filter *info = &stream->filter;
-
-``ppstream_filter`` is the following structure::
-
- typedef struct {
- ppstreamtp *filters; // c-array of filter identifiers (enum integers)
- ppdict **params; // c-array of ppdict pointers
- size_t count; // number of filters, length of the arrays (typically 1)
- } ppstream_filter;
-
-If ``count > 0`` then ``filters`` member is not NULL. Filters array keeps integer constants::
-
- PPSTREAM_BASE16 /* /ASCIIHexDecode */
- PPSTREAM_BASE85 /* /ASCII85Decode */
- PPSTREAM_RUNLENGTH /* /RunLengthDecode */
- PPSTREAM_FLATE /* /FlateDecode */
- PPSTREAM_LZW /* /LZWDecode */
- PPSTREAM_CCITT /* /CCITTFaxDecode */
- PPSTREAM_DCT /* /DCTDecode */
- PPSTREAM_JBIG2 /* /JBIG2Decode */
- PPSTREAM_JPX /* /JPXDecode */
- PPSTREAM_CRYPT /* /Crypt */
-
-Params array keeps corresponding filter parameters (``/DecodeParms``) if present. ``params`` member is not NULL
-if ``count > 0`` and the stream dict has ``/DecodeParms`` entry. Even if ``params`` is there,
-for every N-th filter, ``params[N]`` may be NULL (corresponding to PDF ``null``).
-
-``stream->filter`` keeps the source stream filter information, which may not correspond to the result of stream readers
-(``ppstream_first()``, ``ppstream_next()``, ``ppstream_all()``). The get the filters info relevant to the result from readers::
-
- void ppstream_filter_info (ppstream *stream, ppstream_filter *info, int decode);
-
-The function fills ``ppstream_filter`` structure according to the expected result from stream readers (example 3 shows
-how to use it to reconstruct ``/Filter`` and ``/DecodeParms`` when copying the stream to some other PDF).
-
-To convert filter identifier (``ppstreamtp``) to a corresponding PDF filter name::
-
- const char * ppstream_filter_name[];
-
-To covert ``ppname`` to filter identifier::
-
- int ppstream_filter_type (ppname filtername, ppstreamtp *filtertype);
- // returns 1 and sets filtertype if filtername is the proper filter name
-
-Additional information about the stream can be fetched from macros::
-
- ppstream_compressed(stream) /* stream->flags & (PPSTREAM_FILTER|PPSTREAM_IMAGE) */
- ppstream_filtered(stream) /* stream->flags & PPSTREAM_FILTER */
- ppstream_image(stream) /* stream->flags * PPSTREAM_IMAGE */
-
-``stream->flags`` is a binary sum of the following::
-
- PPSTREAM_FILTER /* set iff the stream filters list has one of: BASE16, BASE85, RUNLENGTH, FLATE, LZW */
- PPSTREAM_IMAGE /* set iff the stream filters list has one of: CCITT, DCT, JBIG2, JPX */
- PPSTREAM_ENCRYPTED /* set iff the stream is encrypted */
- PPSTREAM_ENCRYPTED_OWN /* set iff the stream has own CRYPT filter */
-
-Note that ``PPSTREAM_COMPRESSED`` is not there any longer, use ``ppstream_compressed()`` instead.
-And there is some more, see ``ppapi.h``.
-
-Ref
----
-
-Indirect objects are represented as ``ppref`` structure. To get the object that the
-reference refers to::
-
- ppobj * ppref_obj(ppref *ref) // macro
-
-``ppref`` structure also keeps the reference number and version, a pointer to cross reference table it belongs
-to and others, but I guess you won't need anything but the referenced object. ``pplib`` parser resolves references
-on-fly. So if there is a dict with indirect objects::
-
- <<
- /Type /Page
- /Resources 123 0 R
- ...
- >>
-
-the parser will produce ``ppdict`` with ``Resources`` key pointing the proper ``ppref *`` value.
-If you need more, access ``ppref`` members::
-
- struct ppref {
- ppobj object; // target object
- ppuint number, version; // identifiers
- size_t offset; // file offset (useless for you, may be zero for compressed objects)
- ppuint length; // the length of the original object data
- ppxref *xref; // cross reference table it belongs to
- };
-
-
-XRef
-----
-
-Cross reference table is exposed as ``ppxref`` (incomplete type, you can only oprate on its pointer).
-To get top document xref::
-
- ppxref * ppdoc_xref (ppdoc *pdf);
-
-To get previous (older) xref::
-
- ppxref * ppxref_prev (ppxref *xref);
-
-To find an object of a given refnumber::
-
- ppref * ppxref_find (ppxref *xref, ppuint refnumber);
-
-[Note: since pplib v0.98 in case of documents with incremental update, ``ppxref_find()`` returns
-the newest available version of a given object rather than the object in a given body.]
-
-PDF
----
-
-PDF document is represented as ``ppdoc`` structure (incomplete type, you can only operate on its pointer).
-To load a document from file::
-
- ppdoc * ppdoc_load (const char *filename);
-
-To load a document from memory data::
-
- ppdoc * ppdoc_mem (const void *data, size_t size);
-
-The data is assumed to be a buffer allocated with ``malloc`` - it is freed when destroying ``ppdoc``.
-
-Both loaders returns ``NULL`` on failure.
-
-To free ``ppdoc`` and all objects it refers to::
-
- void ppdoc_free (ppdoc *pdf);
-
-So far we haven't mention about any explicit object reclaimers. There are no dedicated ``free`` functions
-for other objects. You don't allocate or free objects yourself. ``ppdoc`` object is an owner of all
-beings it refers to. It also means that every object described so far is alive as long as the containing
-``ppdoc`` is alive.
-
-To access main PDF dicts::
-
- ppdict * ppdoc_trailer(ppdoc *pdf); // returns top xref trailer dict
- ppdict * ppdoc_catalog(ppdoc *pdf); // returns catalog referred from the trailer
- ppdict * ppdoc_info(ppdoc *pdf); // returns info dict referred from the trailer
-
-To get the PDF version::
-
- const char * ppdoc_version_string (ppdoc *pdf); // version string
- int ppdoc_version_number (ppdoc *pdf, int *minor); // minor and major numbers
-
-To get the file size of the source PDF document::
-
- size_t ppdoc_file_size (ppdoc *pdf);
-
-To get the number of objects in all xrefs::
-
- ppuint ppdoc_objects (ppdoc *pdf);
-
-To get the approx usage of memory::
-
- size_t ppdoc_memory (ppdoc *pdf, size_t *waste);
-
-Encryption
-----------
-
-``pplib`` handles encrypted (password protected) documents. If a document is encrypted, most of strings and streams are ciphered.
-In that form they are unreadable and rather useless, you can't even rewrite such strings/streams as-is to a different PDF output.
-It is a common practise to *protect* documents with an empty password. Such documents remain readable in Acrobat (just opens them without prompting
-for a password), but some features (eg. printing) may restricted by the application.
-
-When ``pplib`` detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, ``pplib`` proceeeds normally, providing
-an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, ``pplib`` gives
-a way to provide a password and proceed. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object wntries
-set to ``null``.
-
-After loading a document you should check encryption status with::
-
- ppcrypt_status ppdoc_crypt_status (ppdoc *pdf);
-
-``ppcrypt_status`` (integer) may have the following values:
-
- ``PPCRYPT_NONE`` - no encryption, go ahead
- ``PPCRYPT_DONE`` - encryption present but password succeeded, go ahead
- ``PPCRYPT_PASS`` - encryption present, need non-empty password
- ``PPCRYPT_FAIL`` - invalid or unsupported encryption (eg. undocumented in pdf spec)
-
-If a password is needed, you can provide one with::
-
- ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength,
- const void *ownerpass, size_t ownerpasslength);
-
-Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough
-to know that having one of them is enough to decrypt the document. If you know the password, you probably mean
-``userpass``, in which case you should put ``NULL`` as ``ownerpass``. The function returns ``PPCRYPT_DONE`` if the password
-succeeds and the previous status otherwise. Your custom loader function may look like that::
-
- ppdoc *pdf;
- pdf = ppdoc_load("file.pdf");
- if (pdf == NULL)
- return NULL;
- switch (ppdoc_crypt_status(pdf))
- {
- case PPCRYPT_NONE:
- case PPCRYPT_DONE:
- return pdf;
- case PPCRYPT_PASS:
- if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE ||
- ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE)
- return pdf;
- printf("sorry, password needed\n");
- ppdoc_free(pdf);
- return NULL;
- case PPCRYPT_FAIL:
- printf("sorry, encryption failed\n");
- ppdoc_free(pdf);
- return NULL;
- }
-
-[If you get ``PPCRYPT_FAIL`` it might mean *I failed*, so treat as a bug.]
-
-If you'd like to know what permissions are given/restricted to encrypted document::
-
- ppint ppdoc_permissions (ppdoc *pdf);
-
-Returned value can be queried with the following binary flags (you can verify with Acrobat *File -> Properties -> Security* tab)::
-
- PPDOC_ALLOW_PRINT // printing
- PPDOC_ALLOW_MODIFY // filling form fields, signing, creating template pages
- PPDOC_ALLOW_COPY // copying, copying for accessibility
- PPDOC_ALLOW_ANNOTS // filling form fields, copying, signing
- PPDOC_ALLOW_EXTRACT // contents copying for accessibility
- PPDOC_ALLOW_ASSEMBLY // (no effect)
- PPDOC_ALLOW_PRINT_HIRES // (no effect)
-
-``pplib`` does absolutelly nothing with permissions, it cares only to decrypt the document. As mentioned, encryption applies to strings
-and streams. ``pplib`` decrypt strings when parsing document objects, so the result you get is *normal* (not ciphered).
-Streams are decrypted whenever you access them. Even if you ask for a raw stream data, you'll get a raw (compressed) stream, but decrypted.
-So except the check to ``ppdoc_crypt_status()``, you shouldn't bother about encryption.
-
-In encrypted documents most of streams are encrypted. To check if a given stream is encrypted::
-
- ppstream_encrypted(stream) // macro, returns non-zero if encrypted
-
-Encryption is independent from compression, don't confuse with ``ppstream_compressed()``
-
-Pages
------
-
-Several helpers to deal with pages. To get the number of pages::
-
- ppuint ppdoc_page_count (ppdoc *pdf);
-
-To access the root pages tree node::
-
- ppref * ppdoc_pages(ppdoc *pdf);
-
-To get the page reference at a given index::
-
- ppref * ppdoc_page (ppdoc *pdf, ppuint index);
-
-``index`` is a page number. First page has number 1. For index out of bounds ``ppdoc_page()`` returns NULL.
-Iterating over pages using index from 1 to ``ppdoc_page_count()`` and calling ``ppdoc_page()`` on each iteration
-would be suboptimal. Here is a dedicted iterator for this::
-
- ppref * ppdoc_first_page (ppdoc *pdf);
- ppref * ppdoc_next_page (ppdoc *pdf);
-
-The iterator in use::
-
- ppdoc *pdf;
- ppref *ref;
- ppdict *dict;
- int pageno;
-
- pdf = ppdoc_load("file.pdf");
- for (ref = ppdoc_first_page(pdf), pageno = 1; ref != NULL; ref = ppdoc_next_page(pdf), ++pageno)
- {
- dict = ppref_obj(obj)->dict; // take for granted it is a dict
- // do something with the page dict
- }
-
-Functions related to pages return ``ppref *`` ensured to contain dict object, so you don't need sanity
-type checks here.
-
-Contents
---------
-
-PDF page contents can be given as a stream or array of streams. Here is a convenience iterator over page
-contents streams::
-
- ppstream * ppcontents_first (ppdict *dict);
- ppstream * ppcontents_next (ppdict *dict, ppstream *stream);
-
-A complete example of contents stream parser use is given below (example 2).
-But before we get there, we need to introduce ``ppcontext`` object. Conceptually,
-``ppcontext`` is an owner (memory handler) of objects created on demand (beyond the ``ppdoc``).
-So far used only with contents stream parser, which might produce quite some data that we want
-to release just after used. To create a new context::
-
- pcontext * ppcontext_new (void);
-
-It initializes a new context and its internal memory heap, taking about 64kB on start. After that,
-the context is ready to produce objects (contents parsing functions below). Once objects produced
-from a given context are no longer needed::
-
- void ppcontext_done (ppcontext *context);
-
-It restores the context to its initial state, as after ``ppcontext_new()``. It means that the context
-is ready to produce another bunch of beings (in the example below, all objects from the next page contents).
-Once the context is not needed anymore::
-
- void ppcontext_free (ppcontext *context);
-
-Now, contents stream parser functions take the context as an argument. Iterator form of contents stream parser
-that allows to process the contents operator by operator::
-
- ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname);
- ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname);
-
-Returned ``ppobj *`` is a pointer to operands list. ``*psize`` is the number of operands on stack.
-The operator itself is stored as ``*pname``.
-
-To parse the entire contents stream at once with no stop at every operator::
-
- ppobj * ppcontents_parse (ppcontext *context, ppstream *stream, size_t *psize);
-
-Returns probably quite long list of all parsed objects (operands and operatos) in one piece.
-The number of objects is stored to ``*psize``.
-
-[Contents may contain so called inline images, that breaks a simple scheme of operands / operator syntax::
-
- BI <keyval pairs> ID <binary image data> EI
-
-Contents parser treats this genuine triplet as a single piece, producing two operands (dict and string)
-followed by ``EI`` operator name.]
-
-Boxes
------
-
-Boxes (rectangles) in PDF are roughly 4-number arrays, but with a special intent.
-``pplib`` provides a basic interface for these special arrays::
-
- typedef struct {
- ppnum lx, ly, rx, ry;
- } pprect;
-
-This type is used only by helper functions - PDF parser is not aware of the rectangle type.
-To convert ``pparray`` to ``pprect``::
-
- pprect * pparray_to_rect (pparray *array, pprect *rect); // returns rect or NULL
-
-In example::
-
- pprect rect;
- if (pparray_to_rect(array, &rect) != NULL)
- ; // do something with rect
-
-To get some image bounding box::
-
- pprect * ppdict_get_rect (ppdict *dict, const char *name, pprect *rect);
- // eg. ppdict_get_rect(imagedict, "BBox", &rect)
-
-To get some page box::
-
- pprect * ppdict_get_box (ppdict *dict, const char *name, pprect *rect);
- // eg. ppdict_get_box(pagedict, "MediaBox", &rect)
-
-The later not only checks the pagedict, but also goes through parent page nodes.
-
-Transforms
-----------
-
-Transformations are given as 6-number arrays, but with a special intent.
-``pplib`` provides a basic interface for these special arrays::
-
- typedef struct {
- ppnum xx, xy, yx, yy, x, y;
- } ppmatrix;
-
-This type is used only by helper functions - PDF parser is not aware of the matrix type.
-To convert ``pparray`` to ``ppmatrix``::
-
- ppmatrix * pparray_to_matrix (pparray *array, ppmatrix *matrix);
-
-In example::
-
- ppmatrix matrix;
- if (pparray_to_matrix(array, &matrix) != NULL)
- ; // do something with matrix
-
-To get the matrix from dict::
-
- ppmatrix * ppdict_get_matrix (ppdict *dict, const char *name, ppmatrix *matrix);
- // eg. ppdict_get_matrix(imagedict, "Matrix", &matrix)
-
-Errors handling
----------------
-
-``pplib`` is not verbose, but might happen that it needs to log some error message, eg. when parsing
-of some PDF boject fails due to invalid offsets. By default, ``pplib`` prints the message to stdout, eg.::
-
- invalid 123 0 R object at offset 123123
-
-To replace the default logger, you can provide your own::
-
- void pplog_callback (pplogger_callback logger, void *alien);
-
-``pplogger_callback`` is a function::
-
- void your_callback (const char *message, void *alien);
-
-In example, to redirect messages to stderr you may define a function::
-
- void your_callback (const char *message, void *alien)
- {
- fprintf((FILE *)alien, "\nooops: %s\n", message);
- }
-
-Then set the callback somewhere before loading documents::
-
- pplog_callback(your_callback, stderr);
-
-(example 2 uses that).
-
-To set the default log messages prefix, eg. ``pplib:``, use::
-
- int pplog_prefix (const char *prefix)
-
-Default is empty. The function succeeds if provided prefix is reasonably short (less then 32 bytes).
+ +``pplib`` +========= + +``pplib`` is a library for raw PDF access. It parses PDF documents and provides an interface to access document structures in C. + +C-API +===== + +Types +----- + +``pplib`` defines several C-types to represent PDF types: + +- ``ppint`` - signed integer (``int64_t``) +- ``ppnum`` - real number (double) +- ``ppname`` - PDF name +- ``ppstring`` - PDF string +- ``pparray`` - PDF array +- ``ppdict`` - PDF dict +- ``ppstream`` - PDF stream +- ``ppref`` - PDF indirect reference +- ``ppobj`` - a container of all above + +Among ``ppint`` and ``ppnum``, we also use ``ppuint`` - unsigned integer (machine word, alias to ``size_t``). + +Other API types: + +- ``ppdoc`` - PDF document +- ``ppxref`` - cross-references table +- ``ppcontext`` - ... later +- ``pprect`` - rectangle +- ``ppmatrix`` - matrix + +Integer, number, name and string are treated as simple types. +Names and strings are actually C-structures, but exposed to API as typedefs to ``const char *``. +Other types (array, dict, stream, reference, object container, xref, PDF) are C-structures, +and you operate it their pointers. So when you declare a simple type variable you say:: + + ppuint u; + ppnum n; + ppname name; + ppstring string; + ... + +And when you declare a compound type you operate on pointers:: + + ppobj *obj; + pparray *array; + ppdict *dict; + ppstream *stream; + ppref *ref; + ppdoc *pdf; + +Some of those C-types are defined in library header ``ppapi.h`` (complete types). Some others are incomplete +(eg. you can't say ``sizeof(ppdoc)`` or ``sizeof(ppxref)``). This is to avoid unnecesary dependencies in +the header. [At some points it's not clear to me what to hide and what to expose, will see.] The library itself +uses ``pplib.h`` but for auxilary applications including a standalone ``ppapi.h`` header should be enough. + +``pplib`` was designed having **read-only** PDF access in mind. Even if some structure is completelly exposed, +so that you can directly access its members, you should treat them as read-only. I don't make them ``const`` because +then all variable declarations would need to be ``const``, which is annoying, and I'd need some trickery in the library +internals to unconst. Besides, nothing is really const for C type casts. + +Object +------ + +A common container for all elementary PDF object types is ``ppobj`` structure. ``ppobj`` has a type identifier +(integer) and union of values:: + + struct ppobj { + ppobjtp type; + union { + ppint integer; + ppnum number; + ppname name; + ppstring string; + pparray *array; + ppdict *dict; + ppstream *stream; + ppref *ref; + void *any; + }; + }; + +Object type is one of constants (enum):: + + PPNONE + PPNULL + PPBOOL + PPINT + PPNUM + PPNAME + PPSTRING + PPARRAY + PPDICT + PPSTREAM + PPREF + +The type determines the structure member you're allowed to access:: + + ppobj *obj; + ... + switch (obj->type) + { + case PPNONE: // shouldn't actually happen, indicates some failure + break; + case PPNULL: // valid PDF null object, no value + break; + case PPBOOL: // do something with obj->integer (ppint), value 0 or 1 + break; + case PPINT: // do something with obj->integer (ppint) + break; + case PPNUM: // do something with obj->number (ppnum) + break; + case PPNAME: // do something with obj->name (ppname) + break; + case PPSTRING: // do something with obj->string (ppstring) + break; + case PPARRAY: // do something with obj->array (pparray *) + break; + case PPDICT: // do something with obj->dict (ppdict *) + break; + case PPSTREAM: // do something with obj->stream (ppstream *) + break; + case PPREF: // do something with obj->ref (ppref *) + break; + } + +More often then not you know exactly what type of object value is expected, in which case +you may use one of the following macros:: + + // returns 1 if o->type is PPNULL + int ppobj_get_null(o) \ + + // if o->type is PPBOOL, sets int v to 0 or 1 and returns 1, 0 otherwise + int ppobj_get_bool(o, v) + + // if o->type is PPINT, sets ppint v and returns 1, 0 otherwise + int ppobj_get_int(o, v) + + // if o->type is PPINT and >= 0, sets ppuint v and returns 1, 0 otherwise + int ppobj_get_uint(o, v) + + // if o->type is PPNUM or PPINT, sets ppnum v and returns 1, 0 otherwise + int ppobj_get_num(o, v) + + // if o->type is PPNAME returns the name, NULL otherwise + ppname ppobj_get_name(o) + + // if o->type is PPSTRING returns the string, NULL otherwise + ppstring ppobj_get_string(o) + + // if o->type is PPARRAY returns the array, NULL otherwise + pparray * ppobj_get_array(o) + + // if o->type is PPDICT returns the dict, NULL otherwise + ppdict * ppobj_get_dict(o) + + // if o->type is PPSTREAM returns the stream, NULL otherwise + ppstream * ppobj_get_stream(o) + + // if o->type is PPREF returns the reference, NULL otherwise + ppref * ppobj_get_ref(o) + +Note the coercion from integer to real number, but not reverse. In practise, whenever you expect a real number, +you should also handle integer (eg. '1' used instead of '1.0'). + +It is a common case that the object is given as an indirect reference, but what you actually +want is not the reference, but the object referred by it. Here is a helper for it:: + + // if o->type is PPREF, returns what the reference points, otherwise returns o + ppobj * ppobj_rget_obj(o) + +Also every ``ppobj_get_*`` macro has ``ppobj_rget_*`` counterpart that makes a check +for the expected type, but if the object is PPREF, it jumps to the target object. +So for example ``ppobj_rget_dict(obj)`` will return dict if ``obj`` is of type PPDICT +or if it is of type PPREF and ``obj->ref`` hosts an object of type PPDICT. + +Names +----- + +PDF names are represented as ``ppname``. +I find it convenient to have ``ppname`` type pretending ``const char *``. This allows to use ``ppname`` +in all C-style string functions like ``printf("%s", name)``. + +Be aware, however, that ``ppname`` is actually a C-structure. It is perfectly ok to cast ``ppname`` to ``const char *``:: + + ppname name; + ... + (const char *)name; + +But reverse is forbidden:: + + const char *cstr = "cstring"; + ... + (ppname)cstr; // expect segmentation fault soon + +For convenient use in C, names are ``'\0'`` terminated. But to get the length of name better always use +``ppname_size()`` macro. ``ppname`` object knows its size, don't use ``strlen()``:: + + size_t ppname_size(ppname name); // macro, returns length of name in bytes + +In current implementation names are not hashed anyhow, so name-to-name comparison is not smarter than ``memcmp()``. +Use macros:: + + int ppname_is(ppname name, "literal"); // to compare ppname with C-literal string + int ppname_eq(ppname name, ppname other); // to compare ppname with a different name + +If you'll use ``pplib`` to parse contents streams, you may need to distinguish names from operators +(more precisely executable names). Names in PDF are preceeded by '/', executable names aren't. In both +cases PDF parser will produce ``ppname`` but can be distingushed with:: + + int ppname_exec(ppname name); // returns non-zero if name is executable + +Names are kept in their raw form, with possible PDF specific escapes (in text below we call it **encoded** form). +Leading '/' is omitted, though. One may need a decoded name, with no PDF escapes. +A pair of functions provides a simple interface to switch between those two forms:: + + ppname ppname_decoded (ppname name); // returns decoded (unescaped) form of the name + ppname ppname_encoded (ppname name); // returns encoded (escaped) form of the name + +In pretty most cases PDF names contains only letters (no special characters, no escapes), so decoded and encoded forms are identical. +In that case both functions simply return the argument. It is ok to call ``ppname_decoded()`` on already decoded form +and ``ppname_encoded()`` on already encoded form. Both forms are produced by PDF objects parser, so accessing ``ppname`` alter ego +in whatever direction needs no extra decoding or allocation costs. + +String +------ + +PDF strings have the same internal construction as names, so most of names description above applies to strings as well. +``ppstring`` is a typedef of ``const char *``, roughly ``'\0'`` terminiated C-string. To get the size of the string:: + + size_t ppstring_size(ppstring string); // macro, returns the length of the string in bytes + +Strings are provided in their raw form, preserving PDF specific escapes, but with no +``()`` or ``<>`` delims. To distinguish plain strings from hex strings:: + + int ppstring_hex(ppstring string); // macro, returns non zero if hex string + +Or if you prefer:: + + switch (ppstring_type(string)) + { + case PPSTRING_PLAIN: // literal string, surrounded by ``(`` and ``)`` in PDF + break; + case PPSTRING_BASE16: // hex string, surrounded by ``<`` and ``>`` in PDF + break; + case PPSTRING_BASE85: // base85 string surrounded by ``<~`` and ``~>`` in PDF + break; + } + +The last is actually Postscript specific, not used in PDF, but I think it might appear in contents streams... +No matter how the string is given in PDF (plain or hex), here are two functions to +switch between encoded and decoded strings forms:: + + ppstring ppstring_decoded (ppstring string); // returns decoded string possibly with PDF escapes + ppstring ppstring_encoded (ppstring string); // returns encoded string with no PDF escapes + +For hex strings, encoded form contains hex digits, while decoded form contains arbitrary bytes (the result of hex decoding). +Plain strings usually contains printable ASCII characters, but they might contain any binary data. +As with names, objects parser produces both forms. The raw form with PDF escapes (or raw hex form) is considered the main one. +Eg. when you access ``obj->string`` you always get the encoded form. At any moment you can switch to its alter ego. + +No matter if the string is plain or hex, if its first two bytes (decoded) are UTF16 BOM, the string +is considered unicode. ``ppstring`` object *knows* it is unicode or not:: + + switch (ppstring_utf(string)) + { + case PPSTRING_UTF16LE: // unicode string, utf16le + break; + case PPSTRING_UTF16BE: // unicode string, utf16be + break; + default: // no unicode + } + +Or simply:: + + if (ppstring_utf(string) != 0) { + // handle unicode string + } + +If the string is unicode, BOM remains the part of the string -- ``pplib`` parser does not strip it. +Unicode or not, encoded or decoded, strings are always C-arrays of bytes and ``ppstring_size()`` +always returns the size in bytes. + +Array +----- + +PDF arrays are represented as ``pparray`` type, which is C-array of ``ppobj`` structures. +To get the size:: + + size_t pparray_size(pparray *array) // macro, returns the number of array items + +To get ``ppobj *`` at a given index:: + + ppobj * pparray_at(array, index) // macro, returns ppobj * (no index check) + ppobj * pparray_get(array, index) // macro, returns ppobj * or NULL (with index check) + ppobj * pparray_get_obj (pparray *array, size_t index); // function equiv to pparray_get() + +Iterating over array elements:: + + pparray *array; + size_t index, size; + ppobj *obj; + for (size = pparray_size(array), pparray_first(array, index, obj); index < size; pparray_next(index, obj)) + { + // do something with index and obj + } + +There is no magic first/next macros, just iteration over pointers. One could also use something like:: + + for (index = 0, size = array->size; index < size; ++index) + { + obj = pparray_at(array, index); + // do something with index and obj + } + +When getting values from array and expecting a result of known type, use one of the following:: + + int pparray_get_bool (pparray *array, size_t index, int *v); // get boolean value + int pparray_get_int (pparray *array, size_t index, ppint *v); // get ppint value + int pparray_get_uint (pparray *array, size_t index, ppuint *v); // get ppuint value + int pparray_get_num (pparray *array, size_t index, ppnum *v); // get ppnum value + ppname pparray_get_name (pparray *array, size_t index); // get ppname value + ppstring pparray_get_string (pparray *array, size_t index); // get ppstring value + pparray * pparray_get_array (pparray *array, size_t index); // get pparray * value + ppdict * pparray_get_dict (pparray *array, size_t index); // get ppdict * value + ppref * pparray_get_ref (pparray *array, size_t index); // get ppref * value + +As with ``ppobj_get_*`` suite, numeric types getters set the value of a given type and returns 1, if the type matches. +Otherwise sets nothing and returns 0. Other getters return the value if the type matches, or NULL. + +Every function from ``pparray_get_*`` suite have its ``pparray_rget_*`` counterpart that +that dereferences indirect objects (as explained for ``ppobj_rget_*`` getters). Note that +there is no ``pparray_get_stream()`` function, as streams in PDF are always indirect. +To get the stream from array use:: + + ppstream * pparray_rget_stream (pparray *array, size_t index); + +Dict +---- + +PDF dicts are represented as ``ppdict`` structure, which is C-array of ``ppobj`` with parallel +C-array of ``ppname`` pointers. To get the size of a dict:: + + size_t ppdict_size(ppdict *dict) // macro, returns the number of key-val pairs + +To get the value at a given index (integer):: + + ppobj * ppdict_at(ppdict *dict, index) // macro, no index check + +To get the name (key) at a given index:: + + ppname ppdict_key(ppdict *dict, index) // macro, no index check + +To iterate over dict key-val pairs:: + + ppdict *dict; + ppname *pkey; + ppobj *obj; + + for (ppdict_first(dict, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj)) + { + // do something with *pkey and obj + } + +There is no magic in first/next macros, just iteration through keys and values lists pointers. +For convenient iteration, a list of keys is terminated with NULL, so in the code above ``*pkey != NULL`` +is used as the loop condition. One may also iterate via indices:: + + ppdict *dict; + size_t index, size; + ppname key; + ppobj *obj; + for (index = 0, size = ppdict_size(dict); index < size; ++index) + { + key = ppdict_key(dict, index); + obj = ppdict_at(dict, index); + // do something with key and obj + } + +To get the object associated with a given name, use one of the following:: + + ppobj * ppdict_get_obj (ppdict *dict, const char *name); + int ppdict_get_bool (ppdict *dict, const char *name, int *v); + int ppdict_get_int (ppdict *dict, const char *name, ppint *v); + int ppdict_get_uint (ppdict *dict, const char *name, ppuint *v); + int ppdict_get_num (ppdict *dict, const char *name, ppnum *v); + ppname ppdict_get_name (ppdict *dict, const char *name); + ppstring ppdict_get_string (ppdict *dict, const char *name); + pparray * ppdict_get_array (ppdict *dict, const char *name); + ppdict * ppdict_get_dict (ppdict *dict, const char *name); + ppref * ppdict_get_ref (ppdict *dict, const char *name); + +Note that all getters accepts ``const char *`` as key, so it is ok to say:: + + ppdict_rget_dict(dict, "Resources"); + +as well as:: + + ppdic_rget_dict(dict, name); // ppname name + +Every ``ppdict_get_*`` getter has ``ppdict_rget_*`` counterpart that dereferences +indirect objects if necessary. Note that there is no ``ppdict_get_stream()`` function, +but there is:: + + ppstream * ppdict_rget_stream (ppdict *dict, const char *name); + +So far dicts comes with no names mapping, so by-name dict accessors perform a linear search +through the keys list. PDF dicts are usually small, so it is fast enough. +Building names lookup for every dict in PDF makes no sense I think, as ``pplib`` applications +will query just several dicts I guess.. However, some apps may extensively query +resources, which may refer to hundreds of objects (eg. images). So some mapping for dicts +is still considered. + +Stream +------ + +PDF streams are represented as ``ppstream`` objects. To get the stream dict:: + + ppdict * ppstream_dict(ppstream *stream) // macro + +To read the stream data:: + + uint8_t * ppstream_first (ppstream *stream, size_t *size, int decode); + uint8_t * ppstream_next (ppstream *stream, size_t *size); + void ppstream_done (ppstream *stream); + +Both ``first` and ``next`` functions return a chunk of stream data and sets the ``size`` of the chunk. +``decode`` parameter tell the reader to decompress the stream (1) or return raw (0). A call to ``ppstream_next()`` +must be preceeded by ``ppstream_first()``. Once you're done with the stream, you have to call ``ppstream_done()``, +no matter if the stream has been read to the end or not. The stream data iterator in use:: + + uint8_t *data; + size_t size; + ppstream *stream; + int decode = 1; // 1 - get decompressed, 0 - get raw + + for (data = ppstream_first(stream, &size, decode); data != NULL; data = ppstream_next(stream, &size)) + { + // do something with data and its size + } + ppstream_done(stream); + +Every subsequent iterator call invalidates the previous reader output, so you have to utilize the returned chunk +of data just after you ot that. So the following is wrong:: + + data1 = ppstream_first(stream, &size, 1); + data2 = ppstream_next(stream, &size); + data3 = ppstream_next(stream, &size); + some_output(data1, size); + some_output(data2, size); + +The reader calls usually return the same pointer to internal buffer, just filled with a different data. +``pplib`` allocates reasonably large buffer and fills that buffer on subsequent calls to the reader. + +If the source stream has no compression, using both ``decode == 1`` and ``decode == 0`` should give the same result. +You can check if the stream is actually compressed with:: + + ppstream_compressed(stream) // macro, returns non zero if /Filter is present + +It might be necessary to load the entire stream data at once:: + + uint8_t * ppstream_all (ppstream *stream, size_t *size, int decode); + +If the initial buffer size is insufficient, it grows until the entire stream data is loaded. You must call +``ppstream_done(stream)`` after using returned data. + +``ppstream_done()`` doesn't invalidate the stream object, it just closes its internal reader. +The stream itself remains a valid object (eg. one can read it again if necessary), +but the reader buffer is released. It is actually not freed but kept for future the reuse with that on some other stream, +but you still need to mark it ready for reuse to avoid allocating a separate buffer for every stream you're going to read. + +Stream data readers will return ``NULL`` if you haven't close the previous reader process with ``ppstream_done()``. All below is wrong:: + + data1 = ppstream_all(stream, &size, 1); + data2 = ppstream_all(stream, &size, 1); // data2 == NULL + // or + data1 = ppstream_first(stream, &size, 1); + data2 = ppstream_first(stream, &size, 1); // data2 == NULL + // or + data1 = ppstream_first(stream, &size, 1); + data2 = ppstream_all(stream, &size, 1); // data2 == NULL + +To avoid unnecessary dependencies, ``pplib`` does not support image filters (``/DCT``, ``/JPX``, ``/JBIG``, ``/CCITT``). +But it is ok to read the stream with ``decode`` set to 1 on such streams. ``pplib`` assumes that the image is the +final/target stream form and just returns it as-is. Eg. in the case of JPEG (``/DCT`` filtered) image both calls should +give the same results:: + + ppstream_all(jpegstream, &jpegsize, 0); // don't decode, return what's there + ppstream_all(jpegstream, &jpegsize, 1); // decode but found image filter, effectively the same + +A bit more about streams memory. As mentioned, ``pplib`` allocates buffers for stream readers. After ``ppstream_done()``, +the stream no longer *owns* the buffer space. But the buffer may remain allocated, to be reused with future readers. +``pplib`` keeps a pool of several buffers. This means, that when you use stream readers, ``pplib`` eats +some memory (1MB or so) that is not freed, even if no streams are used. And even if you free all objects. +If you suffer from this, you can optionally use a pair of functions:: + + void ppstream_init_buffers (void); + void ppstream_free_buffers (void); + +The first initializes buffers pool, unless done so far. Currently ``pplib`` cares of it before opening every stream reader, +so it is not obligatory. The second frees a pool of buffers. The intended use is to call ``ppstream_init_buffers()`` once +as kind of library initializer and to call ``ppstream_free_buffers()`` once, as the library finalizer. + +Filters +------- + +In version v1.00 (20190916) ``ppstream`` API has been extended with filters information. +``ppstream`` knows its filter(s) and keps it as ``stream->filter``:: + + // ppstream *stream; + ppstream_filter *info = &stream->filter; + +``ppstream_filter`` is the following structure:: + + typedef struct { + ppstreamtp *filters; // c-array of filter identifiers (enum integers) + ppdict **params; // c-array of ppdict pointers + size_t count; // number of filters, length of the arrays (typically 1) + } ppstream_filter; + +If ``count > 0`` then ``filters`` member is not NULL. Filters array keeps integer constants:: + + PPSTREAM_BASE16 /* /ASCIIHexDecode */ + PPSTREAM_BASE85 /* /ASCII85Decode */ + PPSTREAM_RUNLENGTH /* /RunLengthDecode */ + PPSTREAM_FLATE /* /FlateDecode */ + PPSTREAM_LZW /* /LZWDecode */ + PPSTREAM_CCITT /* /CCITTFaxDecode */ + PPSTREAM_DCT /* /DCTDecode */ + PPSTREAM_JBIG2 /* /JBIG2Decode */ + PPSTREAM_JPX /* /JPXDecode */ + PPSTREAM_CRYPT /* /Crypt */ + +Params array keeps corresponding filter parameters (``/DecodeParms``) if present. ``params`` member is not NULL +if ``count > 0`` and the stream dict has ``/DecodeParms`` entry. Even if ``params`` is there, +for every N-th filter, ``params[N]`` may be NULL (corresponding to PDF ``null``). + +``stream->filter`` keeps the source stream filter information, which may not correspond to the result of stream readers +(``ppstream_first()``, ``ppstream_next()``, ``ppstream_all()``). The get the filters info relevant to the result from readers:: + + void ppstream_filter_info (ppstream *stream, ppstream_filter *info, int decode); + +The function fills ``ppstream_filter`` structure according to the expected result from stream readers (example 3 shows +how to use it to reconstruct ``/Filter`` and ``/DecodeParms`` when copying the stream to some other PDF). + +To convert filter identifier (``ppstreamtp``) to a corresponding PDF filter name:: + + const char * ppstream_filter_name[]; + +To covert ``ppname`` to filter identifier:: + + int ppstream_filter_type (ppname filtername, ppstreamtp *filtertype); + // returns 1 and sets filtertype if filtername is the proper filter name + +Additional information about the stream can be fetched from macros:: + + ppstream_compressed(stream) /* stream->flags & (PPSTREAM_FILTER|PPSTREAM_IMAGE) */ + ppstream_filtered(stream) /* stream->flags & PPSTREAM_FILTER */ + ppstream_image(stream) /* stream->flags * PPSTREAM_IMAGE */ + +``stream->flags`` is a binary sum of the following:: + + PPSTREAM_FILTER /* set iff the stream filters list has one of: BASE16, BASE85, RUNLENGTH, FLATE, LZW */ + PPSTREAM_IMAGE /* set iff the stream filters list has one of: CCITT, DCT, JBIG2, JPX */ + PPSTREAM_ENCRYPTED /* set iff the stream is encrypted */ + PPSTREAM_ENCRYPTED_OWN /* set iff the stream has own CRYPT filter */ + +Note that ``PPSTREAM_COMPRESSED`` is not there any longer, use ``ppstream_compressed()`` instead. +And there is some more, see ``ppapi.h``. + +Ref +--- + +Indirect objects are represented as ``ppref`` structure. To get the object that the +reference refers to:: + + ppobj * ppref_obj(ppref *ref) // macro + +``ppref`` structure also keeps the reference number and version, a pointer to cross reference table it belongs +to and others, but I guess you won't need anything but the referenced object. ``pplib`` parser resolves references +on-fly. So if there is a dict with indirect objects:: + + << + /Type /Page + /Resources 123 0 R + ... + >> + +the parser will produce ``ppdict`` with ``Resources`` key pointing the proper ``ppref *`` value. +If you need more, access ``ppref`` members:: + + struct ppref { + ppobj object; // target object + ppuint number, version; // identifiers + size_t offset; // file offset (useless for you, may be zero for compressed objects) + ppuint length; // the length of the original object data + ppxref *xref; // cross reference table it belongs to + }; + + +XRef +---- + +Cross reference table is exposed as ``ppxref`` (incomplete type, you can only oprate on its pointer). +To get top document xref:: + + ppxref * ppdoc_xref (ppdoc *pdf); + +To get previous (older) xref:: + + ppxref * ppxref_prev (ppxref *xref); + +To find an object of a given refnumber:: + + ppref * ppxref_find (ppxref *xref, ppuint refnumber); + +[Note: since pplib v0.98 in case of documents with incremental update, ``ppxref_find()`` returns +the newest available version of a given object rather than the object in a given body.] + +PDF +--- + +PDF document is represented as ``ppdoc`` structure (incomplete type, you can only operate on its pointer). +To load a document from file:: + + ppdoc * ppdoc_load (const char *filename); + +To load a document from memory data:: + + ppdoc * ppdoc_mem (const void *data, size_t size); + +The data is assumed to be a buffer allocated with ``malloc`` - it is freed when destroying ``ppdoc``. + +Both loaders returns ``NULL`` on failure. + +To free ``ppdoc`` and all objects it refers to:: + + void ppdoc_free (ppdoc *pdf); + +So far we haven't mention about any explicit object reclaimers. There are no dedicated ``free`` functions +for other objects. You don't allocate or free objects yourself. ``ppdoc`` object is an owner of all +beings it refers to. It also means that every object described so far is alive as long as the containing +``ppdoc`` is alive. + +To access main PDF dicts:: + + ppdict * ppdoc_trailer(ppdoc *pdf); // returns top xref trailer dict + ppdict * ppdoc_catalog(ppdoc *pdf); // returns catalog referred from the trailer + ppdict * ppdoc_info(ppdoc *pdf); // returns info dict referred from the trailer + +To get the PDF version:: + + const char * ppdoc_version_string (ppdoc *pdf); // version string + int ppdoc_version_number (ppdoc *pdf, int *minor); // minor and major numbers + +To get the file size of the source PDF document:: + + size_t ppdoc_file_size (ppdoc *pdf); + +To get the number of objects in all xrefs:: + + ppuint ppdoc_objects (ppdoc *pdf); + +To get the approx usage of memory:: + + size_t ppdoc_memory (ppdoc *pdf, size_t *waste); + +Encryption +---------- + +``pplib`` handles encrypted (password protected) documents. If a document is encrypted, most of strings and streams are ciphered. +In that form they are unreadable and rather useless, you can't even rewrite such strings/streams as-is to a different PDF output. +It is a common practise to *protect* documents with an empty password. Such documents remain readable in Acrobat (just opens them without prompting +for a password), but some features (eg. printing) may restricted by the application. + +When ``pplib`` detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, ``pplib`` proceeeds normally, providing +an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, ``pplib`` gives +a way to provide a password and proceed. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object wntries +set to ``null``. + +After loading a document you should check encryption status with:: + + ppcrypt_status ppdoc_crypt_status (ppdoc *pdf); + +``ppcrypt_status`` (integer) may have the following values: + + ``PPCRYPT_NONE`` - no encryption, go ahead + ``PPCRYPT_DONE`` - encryption present but password succeeded, go ahead + ``PPCRYPT_PASS`` - encryption present, need non-empty password + ``PPCRYPT_FAIL`` - invalid or unsupported encryption (eg. undocumented in pdf spec) + +If a password is needed, you can provide one with:: + + ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength, + const void *ownerpass, size_t ownerpasslength); + +Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough +to know that having one of them is enough to decrypt the document. If you know the password, you probably mean +``userpass``, in which case you should put ``NULL`` as ``ownerpass``. The function returns ``PPCRYPT_DONE`` if the password +succeeds and the previous status otherwise. Your custom loader function may look like that:: + + ppdoc *pdf; + pdf = ppdoc_load("file.pdf"); + if (pdf == NULL) + return NULL; + switch (ppdoc_crypt_status(pdf)) + { + case PPCRYPT_NONE: + case PPCRYPT_DONE: + return pdf; + case PPCRYPT_PASS: + if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE || + ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE) + return pdf; + printf("sorry, password needed\n"); + ppdoc_free(pdf); + return NULL; + case PPCRYPT_FAIL: + printf("sorry, encryption failed\n"); + ppdoc_free(pdf); + return NULL; + } + +[If you get ``PPCRYPT_FAIL`` it might mean *I failed*, so treat as a bug.] + +If you'd like to know what permissions are given/restricted to encrypted document:: + + ppint ppdoc_permissions (ppdoc *pdf); + +Returned value can be queried with the following binary flags (you can verify with Acrobat *File -> Properties -> Security* tab):: + + PPDOC_ALLOW_PRINT // printing + PPDOC_ALLOW_MODIFY // filling form fields, signing, creating template pages + PPDOC_ALLOW_COPY // copying, copying for accessibility + PPDOC_ALLOW_ANNOTS // filling form fields, copying, signing + PPDOC_ALLOW_EXTRACT // contents copying for accessibility + PPDOC_ALLOW_ASSEMBLY // (no effect) + PPDOC_ALLOW_PRINT_HIRES // (no effect) + +``pplib`` does absolutelly nothing with permissions, it cares only to decrypt the document. As mentioned, encryption applies to strings +and streams. ``pplib`` decrypt strings when parsing document objects, so the result you get is *normal* (not ciphered). +Streams are decrypted whenever you access them. Even if you ask for a raw stream data, you'll get a raw (compressed) stream, but decrypted. +So except the check to ``ppdoc_crypt_status()``, you shouldn't bother about encryption. + +In encrypted documents most of streams are encrypted. To check if a given stream is encrypted:: + + ppstream_encrypted(stream) // macro, returns non-zero if encrypted + +Encryption is independent from compression, don't confuse with ``ppstream_compressed()`` + +Pages +----- + +Several helpers to deal with pages. To get the number of pages:: + + ppuint ppdoc_page_count (ppdoc *pdf); + +To access the root pages tree node:: + + ppref * ppdoc_pages(ppdoc *pdf); + +To get the page reference at a given index:: + + ppref * ppdoc_page (ppdoc *pdf, ppuint index); + +``index`` is a page number. First page has number 1. For index out of bounds ``ppdoc_page()`` returns NULL. +Iterating over pages using index from 1 to ``ppdoc_page_count()`` and calling ``ppdoc_page()`` on each iteration +would be suboptimal. Here is a dedicted iterator for this:: + + ppref * ppdoc_first_page (ppdoc *pdf); + ppref * ppdoc_next_page (ppdoc *pdf); + +The iterator in use:: + + ppdoc *pdf; + ppref *ref; + ppdict *dict; + int pageno; + + pdf = ppdoc_load("file.pdf"); + for (ref = ppdoc_first_page(pdf), pageno = 1; ref != NULL; ref = ppdoc_next_page(pdf), ++pageno) + { + dict = ppref_obj(obj)->dict; // take for granted it is a dict + // do something with the page dict + } + +Functions related to pages return ``ppref *`` ensured to contain dict object, so you don't need sanity +type checks here. + +Contents +-------- + +PDF page contents can be given as a stream or array of streams. Here is a convenience iterator over page +contents streams:: + + ppstream * ppcontents_first (ppdict *dict); + ppstream * ppcontents_next (ppdict *dict, ppstream *stream); + +A complete example of contents stream parser use is given below (example 2). +But before we get there, we need to introduce ``ppcontext`` object. Conceptually, +``ppcontext`` is an owner (memory handler) of objects created on demand (beyond the ``ppdoc``). +So far used only with contents stream parser, which might produce quite some data that we want +to release just after used. To create a new context:: + + pcontext * ppcontext_new (void); + +It initializes a new context and its internal memory heap, taking about 64kB on start. After that, +the context is ready to produce objects (contents parsing functions below). Once objects produced +from a given context are no longer needed:: + + void ppcontext_done (ppcontext *context); + +It restores the context to its initial state, as after ``ppcontext_new()``. It means that the context +is ready to produce another bunch of beings (in the example below, all objects from the next page contents). +Once the context is not needed anymore:: + + void ppcontext_free (ppcontext *context); + +Now, contents stream parser functions take the context as an argument. Iterator form of contents stream parser +that allows to process the contents operator by operator:: + + ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname); + ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname); + +Returned ``ppobj *`` is a pointer to operands list. ``*psize`` is the number of operands on stack. +The operator itself is stored as ``*pname``. + +To parse the entire contents stream at once with no stop at every operator:: + + ppobj * ppcontents_parse (ppcontext *context, ppstream *stream, size_t *psize); + +Returns probably quite long list of all parsed objects (operands and operatos) in one piece. +The number of objects is stored to ``*psize``. + +[Contents may contain so called inline images, that breaks a simple scheme of operands / operator syntax:: + + BI <keyval pairs> ID <binary image data> EI + +Contents parser treats this genuine triplet as a single piece, producing two operands (dict and string) +followed by ``EI`` operator name.] + +Boxes +----- + +Boxes (rectangles) in PDF are roughly 4-number arrays, but with a special intent. +``pplib`` provides a basic interface for these special arrays:: + + typedef struct { + ppnum lx, ly, rx, ry; + } pprect; + +This type is used only by helper functions - PDF parser is not aware of the rectangle type. +To convert ``pparray`` to ``pprect``:: + + pprect * pparray_to_rect (pparray *array, pprect *rect); // returns rect or NULL + +In example:: + + pprect rect; + if (pparray_to_rect(array, &rect) != NULL) + ; // do something with rect + +To get some image bounding box:: + + pprect * ppdict_get_rect (ppdict *dict, const char *name, pprect *rect); + // eg. ppdict_get_rect(imagedict, "BBox", &rect) + +To get some page box:: + + pprect * ppdict_get_box (ppdict *dict, const char *name, pprect *rect); + // eg. ppdict_get_box(pagedict, "MediaBox", &rect) + +The later not only checks the pagedict, but also goes through parent page nodes. + +Transforms +---------- + +Transformations are given as 6-number arrays, but with a special intent. +``pplib`` provides a basic interface for these special arrays:: + + typedef struct { + ppnum xx, xy, yx, yy, x, y; + } ppmatrix; + +This type is used only by helper functions - PDF parser is not aware of the matrix type. +To convert ``pparray`` to ``ppmatrix``:: + + ppmatrix * pparray_to_matrix (pparray *array, ppmatrix *matrix); + +In example:: + + ppmatrix matrix; + if (pparray_to_matrix(array, &matrix) != NULL) + ; // do something with matrix + +To get the matrix from dict:: + + ppmatrix * ppdict_get_matrix (ppdict *dict, const char *name, ppmatrix *matrix); + // eg. ppdict_get_matrix(imagedict, "Matrix", &matrix) + +Errors handling +--------------- + +``pplib`` is not verbose, but might happen that it needs to log some error message, eg. when parsing +of some PDF boject fails due to invalid offsets. By default, ``pplib`` prints the message to stdout, eg.:: + + invalid 123 0 R object at offset 123123 + +To replace the default logger, you can provide your own:: + + void pplog_callback (pplogger_callback logger, void *alien); + +``pplogger_callback`` is a function:: + + void your_callback (const char *message, void *alien); + +In example, to redirect messages to stderr you may define a function:: + + void your_callback (const char *message, void *alien) + { + fprintf((FILE *)alien, "\nooops: %s\n", message); + } + +Then set the callback somewhere before loading documents:: + + pplog_callback(your_callback, stderr); + +(example 2 uses that). + +To set the default log messages prefix, eg. ``pplib:``, use:: + + int pplog_prefix (const char *prefix) + +Default is empty. The function succeeds if provided prefix is reasonably short (less then 32 bytes). diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppcode.rst.txt b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppcode.rst.txt new file mode 100644 index 00000000000..ebe92465d80 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppcode.rst.txt @@ -0,0 +1,101 @@ +Examples
+========
+
+Example 1
+---------
+
+.. literalinclude:: ../src/pptest1.c
+
+Example 2
+---------
+
+.. literalinclude:: ../src/pptest2.c
+
+Example 3
+---------
+
+.. literalinclude:: ../src/pptest3.c
+
+ppapi.h
+-------
+
+.. literalinclude:: ../src/ppapi.h
+
+
+Changes
+=======
+
+v0.97
+-----
+First release integrated with luatex sources, plus portability changes from Luigi.
+
+v0.98
+-----
+Changed references resolving in case of incremental updates; tech notes ppxref_find() in ppxref.c.
+
+v0.99
+-----
+Fixed streams handling; null characters should NOT be gobbled after "stream" keyword
+
+v1.00
+-----
+Fixed streams handling (Luigi); object streams updated before other streams
+Revised streams handling, ppstream API extended
+
+v1.01
+-----
+Fixed names handling (thanks Hans); digits after '#' weren't skipped
+
+v1.02
+-----
+Fixed page finder (thanks Luigi)
+
+v1.03
+-----
+Fixed TIFF predictor (thanks folks)
+
+v1.04
+-----
+Fixed TIFF predictor for ARM
+
+v1.05
+-----
+Attempt to fix parsing inline images crap
+
+v2.00
+-----
+Deep rework on allocators.
+Deep rework on strings and names.
+
+v2.01
+-----
+Fixed invalid stream buffer handling; ``iof_discard()`` no longer reclaims the source (``filter->next``) filter.
+Sanity alignment adjustments in ``iof_heap``.
+
+v2.02
+-----
+Fixed incorrect encoding of strings alterego with octal escaping, thanks Luigi.
+On Hans request added ``ppdoc_filehandle()`` function and ``ppdoc_file()`` macro for loading ppdoc from ``FILE *``.
+
+v2.03
+-----
+Fixed alloc/free of ``ppdoc`` heap; ``ppdoc`` is now mallocated, no longer taken from its own heap. Again, thanks Luigi.
+Fixed warnings about dereferencing type-puned pointers, and some others.
+
+v2.04
+-----
+Byte lookups for names/strings loaders are now int8_t, as char might be signed.
+ppdoc_first_page() / ppdoc_next_page() iterator now handles a case when /Kids array is empty.
+Fixed generating keys for encrypted streams; ppstring_internal() returns the string of the proper size.
+More stream tests in pptest3.c.
+Some rework on md5 and sha2.
+
+v2.05
+-----
+uint8_t instead of ppbyte in internals; ppbyte intent is "the most natural 8-bit integer", so it is 'char',
+but internally we almost always need uint8_t (char may be signed or not..)
+
+TODO
+====
+- external streams (egzotic)
+
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_sources/pplib.rst.txt b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/pplib.rst.txt index 9cf1e996bb2..763dc79cf62 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_sources/pplib.rst.txt +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/pplib.rst.txt @@ -9,5 +9,7 @@ pplib .. toctree::
:maxdepth: 2
- ppapi
+ ppnew
+ ppapi-2.x
+ ppapi-1.x
ppcode
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppnew.rst.txt b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppnew.rst.txt new file mode 100644 index 00000000000..4a0a3b42887 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_sources/ppnew.rst.txt @@ -0,0 +1,103 @@ +
+1.x vs 2.x
+==========
+
+Allocation
+----------
+
+Allocation mechanisms has been revised. All objects are still allocated from a private storage (called heap),
+but now the heap serves properly aligned memory chunks. Implementation of the heap is (hopefully) platform
+independent, so all ``ARM_COMPLIANT`` checks has been removed. Some details work differently on 32/64-bit
+machines, this distinction seems inevitable. Allocation related code has been moved to ``util/utilmem*.c`` files.
+
+[There are actually 3 different allocators - **heap**, **stock**, and **pool** - each of which has 4 variants
+for 1, 2, 4 and 8 bytes alignment. So far ``pplib`` uses only the **heap**, but I want to have this part
+in a single place for a while. More notes about allocators in ``utilmemallc.h``.]
+
+``pplib`` uses two heaps:
+
+* bytes heap - providing 2-bytes aligned memory chunks for byte data
+* structures heap - providing 8-bytes aligned chunks for all structures
+
+2-bytes alignment of byte data is caused by implementation details / limits, ``pplib`` doesn't make a use of it
+(could be unaligned as well). All the structures are stored in 8-bytes aligned chunks on both 32 and 64-bit machines
+(in some structures we use ``double`` and ``int64_t``, which generally needs 8-bytes).
+
+Strings And Names
+-----------------
+
+So far, both ``ppname`` and ``ppstring`` were aliases to ``char *`` with an extra structure hidden just below
+the data address. The idea was to make a string or name usable whenever chars array can, at the cost of some
+pointers trickery. Both names and strings keep an information about pdf-encoded data, as well as plain bytes data.
+I implemented this feature once ``pplib 1.0`` was almost done, and to avoid a revolution, I made that with yet
+another trick. This all was dirty and caused lots of alignment issues.
+
+Now ``ppstring`` and ``ppname`` are **structures**, keeping data and size members, pretty much like ``pparray``::
+
+ struct ppname {
+ ppbyte *data;
+ size_t size;
+ ppname *alterego;
+ int flags;
+ };
+
+ struct ppstring {
+ ppbyte *data;
+ size_t size;
+ ppstring *alterego;
+ int flags;
+ };
+
+Data member is a pointer to (2-bytes aligned) bytes array -- ``ppbyte *``. ``ppbyte`` is an alias to ``char``.
+``pplib`` makes no assumptions about ``ppbyte`` signedness. [I'd prefer to have ``uint8_t``, but better
+keep that in sync with ``ppdict_get_*`` suite, which accepts ``char *``. Using ``"string literals"``
+with ``ppdict_get`` function is the most common case, I guess.]
+
+``ppname_size()`` and ``ppstring_size() `` now have
+trivial ``ppname_data()`` and ``ppstring_data()`` counterparts::
+
+ #define ppname_size(name) ((name)->size)
+ #define ppname_data(name) ((name)->data)
+
+ #define ppstring_size(string) ((string)->size)
+ #define ppstring_data(string) ((string)->data)
+
+Switching between encoded / decoded variants is made via explicit ``alterego`` member. If encoded and decoded forms
+are identical, then ``self->alfterego == self`` (never NULL). Helper functions for that::
+
+ PPAPI ppname * ppname_decoded (ppname *name);
+ PPAPI ppname * ppname_encoded (ppname *name);
+
+ PPAPI ppbyte * ppname_decoded_data (ppname *name);
+ PPAPI ppbyte * ppname_encoded_data (ppname *name);
+
+ PPAPI ppstring * ppstring_decoded (ppstring *string);
+ PPAPI ppstring * ppstring_encoded (ppstring *string);
+
+ PPAPI ppbyte * ppstring_decoded_data (ppstring *string);
+ PPAPI ppbyte * ppstring_encoded_data (ppstring *string);
+
+Since ``ppname`` and ``ppstring`` are now structures, all API functions returning name/string or taking name/string
+as an argument, now take **a pointer to name/string**. Watch out for ``ppdict_get_*`` functions suite. They still accept
+``const char *`` key as an argument, but ``ppname`` type can no longer be used there::
+
+ ppname key;
+ ppdict_get_something(dict, key); // wrong
+ ppdict_get_something(dict, key.data); // ok
+
+ ppname *pkey;
+ ppdict_get_something(dict, (const char *)pkey); // wrong
+ ppdict_get_something(dict, pkey->data); // ok
+
+Consequently, functions / macros that used pointer to ``ppname`` (``ppdict_first()`` / ``ppdict_next()``),
+now needs ``ppname **pname``.
+
+Cleanups
+--------
+
+Some of unused utils were removed. There is still some code in utils part that is not used by the library,
+but I need this tollbox in many other places and don't want to maintain two versions.
+
+Some unification in integer types; ``size_t`` seems to be the best choice for and integer representing machine
+word (``unsigned long`` is not long enough on windows), less utils dependencies, less compiler warnings.
+
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/ajax-loader.gif b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/ajax-loader.gif Binary files differindex 61faf8cab23..61faf8cab23 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/ajax-loader.gif +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/ajax-loader.gif diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/background_b01.png b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/background_b01.png Binary files differindex 353f26dde08..353f26dde08 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/background_b01.png +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/background_b01.png diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/basic.css b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/basic.css index 19ced1057ae..0807176ec0c 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/basic.css +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/basic.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- basic theme. * - * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -81,6 +81,10 @@ div.sphinxsidebar input { font-size: 1em; } +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + div.sphinxsidebar #searchbox input[type="text"] { float: left; width: 80%; @@ -427,6 +431,13 @@ table.field-list td, table.field-list th { hyphens: manual; } +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist td { + vertical-align: top; +} + + /* -- other body styles ----------------------------------------------------- */ ol.arabic { diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/bizstyle.css b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/bizstyle.css index 0464a74e637..0464a74e637 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/bizstyle.css +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/bizstyle.css diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/bizstyle.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/bizstyle.js index 6614fe388d1..6614fe388d1 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/bizstyle.js +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/bizstyle.js diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/comment-bright.png b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/comment-bright.png Binary files differindex 15e27edb12a..15e27edb12a 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/comment-bright.png +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/comment-bright.png diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/comment-close.png b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/comment-close.png Binary files differindex 4d91bcf57de..4d91bcf57de 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/comment-close.png +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/comment-close.png diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/comment.png b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/comment.png Binary files differindex dfbc0cbd512..dfbc0cbd512 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/comment.png +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/comment.png diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/css3-mediaqueries.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/css3-mediaqueries.js index 59735f59dcb..59735f59dcb 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/css3-mediaqueries.js +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/css3-mediaqueries.js diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/css3-mediaqueries_src.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/css3-mediaqueries_src.js index f21dd4949aa..f21dd4949aa 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/css3-mediaqueries_src.js +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/css3-mediaqueries_src.js diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/doctools.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/doctools.js index d8928926bf2..344db17ddbb 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/doctools.js +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/doctools.js @@ -4,7 +4,7 @@ * * Sphinx JavaScript utilities for all documentation. * - * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -150,7 +150,9 @@ var Documentation = { this.fixFirefoxAnchorBug(); this.highlightSearchWords(); this.initIndexTable(); - + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } }, /** @@ -310,4 +312,4 @@ _ = Documentation.gettext; $(document).ready(function() { Documentation.init(); -});
\ No newline at end of file +}); diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/documentation_options.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/documentation_options.js new file mode 100644 index 00000000000..bee34fe6e64 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/documentation_options.js @@ -0,0 +1,10 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '0.1', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + FILE_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, +};
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/down-pressed.png b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/down-pressed.png Binary files differindex 5756c8cad88..5756c8cad88 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/down-pressed.png +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/down-pressed.png diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/down.png b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/down.png Binary files differindex 1b3bdad2cef..1b3bdad2cef 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/down.png +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/down.png diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/file.png b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/file.png Binary files differindex a858a410e4f..a858a410e4f 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/file.png +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/file.png diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/jquery-3.2.1.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/jquery-3.2.1.js index d2d8ca4790e..d2d8ca4790e 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/jquery-3.2.1.js +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/jquery-3.2.1.js diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/jquery.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/jquery.js index 644d35e274f..644d35e274f 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/jquery.js +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/jquery.js diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/language_data.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/language_data.js new file mode 100644 index 00000000000..5266fb19ecb --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/language_data.js @@ -0,0 +1,297 @@ +/* + * language_data.js + * ~~~~~~~~~~~~~~~~ + * + * This script contains the language-specific data used by searchtools.js, + * namely the list of stopwords, stemmer, scorer and splitter. + * + * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; + + +/* Non-minified version JS is _stemmer.js if file is provided */ +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + + + + + +var splitChars = (function() { + var result = {}; + var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, + 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702, + 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971, + 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345, + 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761, + 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823, + 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125, + 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695, + 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587, + 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141]; + var i, j, start, end; + for (i = 0; i < singles.length; i++) { + result[singles[i]] = true; + } + var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709], + [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161], + [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568], + [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807], + [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047], + [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383], + [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450], + [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547], + [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673], + [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820], + [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946], + [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023], + [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173], + [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332], + [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481], + [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718], + [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791], + [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095], + [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205], + [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687], + [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968], + [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869], + [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102], + [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271], + [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592], + [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822], + [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167], + [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959], + [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143], + [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318], + [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483], + [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101], + [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567], + [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292], + [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444], + [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783], + [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311], + [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511], + [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774], + [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071], + [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263], + [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519], + [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647], + [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967], + [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295], + [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274], + [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007], + [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381], + [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]]; + for (i = 0; i < ranges.length; i++) { + start = ranges[i][0]; + end = ranges[i][1]; + for (j = start; j <= end; j++) { + result[j] = true; + } + } + return result; +})(); + +function splitQuery(query) { + var result = []; + var start = -1; + for (var i = 0; i < query.length; i++) { + if (splitChars[query.charCodeAt(i)]) { + if (start !== -1) { + result.push(query.slice(start, i)); + start = -1; + } + } else if (start === -1) { + start = i; + } + } + if (start !== -1) { + result.push(query.slice(start)); + } + return result; +} + + diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/minus.png b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/minus.png Binary files differindex d96755fdaf8..d96755fdaf8 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/minus.png +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/minus.png diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/plus.png b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/plus.png Binary files differindex 7107cec93a9..7107cec93a9 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/plus.png +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/plus.png diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/pygments.css b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/pygments.css index a5e279dcaea..a5e279dcaea 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/pygments.css +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/pygments.css diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/searchtools.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/searchtools.js index 41b83367764..5ff318066d8 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/searchtools.js +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/searchtools.js @@ -1,331 +1,52 @@ /* - * searchtools.js_t + * searchtools.js * ~~~~~~~~~~~~~~~~ * * Sphinx JavaScript utilities for the full-text search. * - * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ - -/* Non-minified version JS is _stemmer.js if file is provided */ -/** - * Porter Stemmer - */ -var Stemmer = function() { - - var step2list = { - ational: 'ate', - tional: 'tion', - enci: 'ence', - anci: 'ance', - izer: 'ize', - bli: 'ble', - alli: 'al', - entli: 'ent', - eli: 'e', - ousli: 'ous', - ization: 'ize', - ation: 'ate', - ator: 'ate', - alism: 'al', - iveness: 'ive', - fulness: 'ful', - ousness: 'ous', - aliti: 'al', - iviti: 'ive', - biliti: 'ble', - logi: 'log' - }; - - var step3list = { - icate: 'ic', - ative: '', - alize: 'al', - iciti: 'ic', - ical: 'ic', - ful: '', - ness: '' +if (!Scorer) { + /** + * Simple result scoring code. + */ + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [filename, title, anchor, descr, score] + // and returns the new score. + /* + score: function(result) { + return result[4]; + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: {0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5}, // used to be unimportantResults + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + // query found in terms + term: 5 }; - - var c = "[^aeiou]"; // consonant - var v = "[aeiouy]"; // vowel - var C = c + "[^aeiouy]*"; // consonant sequence - var V = v + "[aeiou]*"; // vowel sequence - - var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 - var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 - var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 - var s_v = "^(" + C + ")?" + v; // vowel in stem - - this.stemWord = function (w) { - var stem; - var suffix; - var firstch; - var origword = w; - - if (w.length < 3) - return w; - - var re; - var re2; - var re3; - var re4; - - firstch = w.substr(0,1); - if (firstch == "y") - w = firstch.toUpperCase() + w.substr(1); - - // Step 1a - re = /^(.+?)(ss|i)es$/; - re2 = /^(.+?)([^s])s$/; - - if (re.test(w)) - w = w.replace(re,"$1$2"); - else if (re2.test(w)) - w = w.replace(re2,"$1$2"); - - // Step 1b - re = /^(.+?)eed$/; - re2 = /^(.+?)(ed|ing)$/; - if (re.test(w)) { - var fp = re.exec(w); - re = new RegExp(mgr0); - if (re.test(fp[1])) { - re = /.$/; - w = w.replace(re,""); - } - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1]; - re2 = new RegExp(s_v); - if (re2.test(stem)) { - w = stem; - re2 = /(at|bl|iz)$/; - re3 = new RegExp("([^aeiouylsz])\\1$"); - re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re2.test(w)) - w = w + "e"; - else if (re3.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - else if (re4.test(w)) - w = w + "e"; - } - } - - // Step 1c - re = /^(.+?)y$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(s_v); - if (re.test(stem)) - w = stem + "i"; - } - - // Step 2 - re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step2list[suffix]; - } - - // Step 3 - re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step3list[suffix]; - } - - // Step 4 - re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; - re2 = /^(.+?)(s|t)(ion)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - if (re.test(stem)) - w = stem; - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1] + fp[2]; - re2 = new RegExp(mgr1); - if (re2.test(stem)) - w = stem; - } - - // Step 5 - re = /^(.+?)e$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - re2 = new RegExp(meq1); - re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) - w = stem; - } - re = /ll$/; - re2 = new RegExp(mgr1); - if (re.test(w) && re2.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - - // and turn initial Y back to y - if (firstch == "y") - w = firstch.toLowerCase() + w.substr(1); - return w; - } } - - -/** - * Simple result scoring code. - */ -var Scorer = { - // Implement the following function to further tweak the score for each result - // The function takes a result array [filename, title, anchor, descr, score] - // and returns the new score. - /* - score: function(result) { - return result[4]; - }, - */ - - // query matches the full name of an object - objNameMatch: 11, - // or matches in the last dotted part of the object name - objPartialMatch: 6, - // Additive scores depending on the priority of the object - objPrio: {0: 15, // used to be importantResults - 1: 5, // used to be objectResults - 2: -5}, // used to be unimportantResults - // Used when the priority is not in the mapping. - objPrioDefault: 0, - - // query found in title - title: 15, - // query found in terms - term: 5 -}; - - - - - -var splitChars = (function() { - var result = {}; - var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, - 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702, - 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971, - 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345, - 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761, - 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823, - 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125, - 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695, - 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587, - 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141]; - var i, j, start, end; - for (i = 0; i < singles.length; i++) { - result[singles[i]] = true; - } - var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709], - [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161], - [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568], - [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807], - [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047], - [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383], - [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450], - [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547], - [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673], - [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820], - [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946], - [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023], - [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173], - [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332], - [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481], - [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718], - [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791], - [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095], - [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205], - [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687], - [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968], - [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869], - [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102], - [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271], - [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592], - [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822], - [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167], - [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959], - [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143], - [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318], - [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483], - [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101], - [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567], - [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292], - [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444], - [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783], - [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311], - [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511], - [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774], - [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071], - [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263], - [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519], - [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647], - [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967], - [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295], - [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274], - [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007], - [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381], - [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]]; - for (i = 0; i < ranges.length; i++) { - start = ranges[i][0]; - end = ranges[i][1]; - for (j = start; j <= end; j++) { - result[j] = true; - } - } - return result; -})(); - -function splitQuery(query) { - var result = []; - var start = -1; - for (var i = 0; i < query.length; i++) { - if (splitChars[query.charCodeAt(i)]) { - if (start !== -1) { - result.push(query.slice(start, i)); - start = -1; - } - } else if (start === -1) { - start = i; - } - } - if (start !== -1) { - result.push(query.slice(start)); - } - return result; +if (!splitQuery) { + function splitQuery(query) { + return query.split(/\s+/); + } } - - - /** * Search Module */ @@ -417,7 +138,6 @@ var Search = { */ query : function(query) { var i; - var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; // stem the searchterms and add them to the correct list var stemmer = new Stemmer(); @@ -758,4 +478,4 @@ var Search = { $(document).ready(function() { Search.init(); -});
\ No newline at end of file +}); diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/underscore-1.3.1.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/underscore-1.3.1.js index 208d4cd890c..208d4cd890c 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/underscore-1.3.1.js +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/underscore-1.3.1.js diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/underscore.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/underscore.js index 5b55f32beac..5b55f32beac 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/underscore.js +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/underscore.js diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/up-pressed.png b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/up-pressed.png Binary files differindex acee3b68efb..acee3b68efb 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/up-pressed.png +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/up-pressed.png diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/up.png b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/up.png Binary files differindex 2a940a7da7c..2a940a7da7c 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/up.png +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/up.png diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/websupport.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/websupport.js index 78e14bb4a1e..3b4999ebf2e 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/websupport.js +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/_static/websupport.js @@ -4,7 +4,7 @@ * * sphinx.websupport utilities for all documentation. * - * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/genindex.html b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/genindex.html index 91d2e44e3e6..24eed9d3c25 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/genindex.html +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/genindex.html @@ -10,10 +10,12 @@ <title>Index — pplib 0.1 documentation</title> <link rel="stylesheet" href="_static/bizstyle.css" type="text/css" /> <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> - <script type="text/javascript" src="_static/documentation_options.js"></script> + + <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> <script type="text/javascript" src="_static/jquery.js"></script> <script type="text/javascript" src="_static/underscore.js"></script> <script type="text/javascript" src="_static/doctools.js"></script> + <script type="text/javascript" src="_static/language_data.js"></script> <script type="text/javascript" src="_static/bizstyle.js"></script> <link rel="index" title="Index" href="#" /> <link rel="search" title="Search" href="search.html" /> @@ -76,8 +78,8 @@ </ul> </div> <div class="footer" role="contentinfo"> - © Copyright 2018, p.jackowski@gust.org.pl. - Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.4. + © Copyright 2019, p.jackowski@gust.org.pl. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5. </div> </body> </html>
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/objects.inv b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/objects.inv new file mode 100644 index 00000000000..96b6c59e0d3 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/objects.inv @@ -0,0 +1,6 @@ +# Sphinx inventory version 2 +# Project: pplib +# Version: +# The remainder of this file is compressed using zlib. +xÚm=à FwNÁˆÆî:TªÔ°?VIÛôöL¤læ}ï“…è¢çÍ\¼ZÀs1sÛé´nÁó[YHæÄÄŸ8’ïɼ=ô¢B'æ‰J&éV9 ½[xyv[žÙr´e³u20ª•wÝU@™Qa° + I”4ÂwL ´žýÉmWõÒëøsb¤>)(ìä^r¡
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppapi-1.x.html b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppapi-1.x.html new file mode 100644 index 00000000000..838aee52175 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppapi-1.x.html @@ -0,0 +1,1030 @@ + + +<!doctype html> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>pplib 1.x — pplib 0.1 documentation</title> + <link rel="stylesheet" href="_static/bizstyle.css" type="text/css" /> + <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> + + <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> + <script type="text/javascript" src="_static/jquery.js"></script> + <script type="text/javascript" src="_static/underscore.js"></script> + <script type="text/javascript" src="_static/doctools.js"></script> + <script type="text/javascript" src="_static/language_data.js"></script> + <script type="text/javascript" src="_static/bizstyle.js"></script> + <link rel="index" title="Index" href="genindex.html" /> + <link rel="search" title="Search" href="search.html" /> + <link rel="next" title="Examples" href="ppcode.html" /> + <link rel="prev" title="pplib 2.x" href="ppapi-2.x.html" /> + <meta name="viewport" content="width=device-width,initial-scale=1.0"> + <!--[if lt IE 9]> + <script type="text/javascript" src="_static/css3-mediaqueries.js"></script> + <![endif]--> + </head><body> + <div class="related" role="navigation" aria-label="related navigation"> + <h3>Navigation</h3> + <ul> + <li class="right" style="margin-right: 10px"> + <a href="genindex.html" title="General Index" + accesskey="I">index</a></li> + <li class="right" > + <a href="ppcode.html" title="Examples" + accesskey="N">next</a> |</li> + <li class="right" > + <a href="ppapi-2.x.html" title="pplib 2.x" + accesskey="P">previous</a> |</li> + <li class="nav-item nav-item-0"><a href="pplib.html">pplib 0.1 documentation</a> »</li> + </ul> + </div> + <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> + <div class="sphinxsidebarwrapper"> + <h3><a href="pplib.html">Table of Contents</a></h3> + <ul> +<li><a class="reference internal" href="#"><code class="docutils literal notranslate"><span class="pre">pplib</span></code> 1.x</a></li> +<li><a class="reference internal" href="#c-api">C-API</a><ul> +<li><a class="reference internal" href="#types">Types</a></li> +<li><a class="reference internal" href="#object">Object</a></li> +<li><a class="reference internal" href="#names">Names</a></li> +<li><a class="reference internal" href="#string">String</a></li> +<li><a class="reference internal" href="#array">Array</a></li> +<li><a class="reference internal" href="#dict">Dict</a></li> +<li><a class="reference internal" href="#stream">Stream</a></li> +<li><a class="reference internal" href="#filters">Filters</a></li> +<li><a class="reference internal" href="#ref">Ref</a></li> +<li><a class="reference internal" href="#xref">XRef</a></li> +<li><a class="reference internal" href="#pdf">PDF</a></li> +<li><a class="reference internal" href="#encryption">Encryption</a></li> +<li><a class="reference internal" href="#pages">Pages</a></li> +<li><a class="reference internal" href="#contents">Contents</a></li> +<li><a class="reference internal" href="#boxes">Boxes</a></li> +<li><a class="reference internal" href="#transforms">Transforms</a></li> +<li><a class="reference internal" href="#errors-handling">Errors handling</a></li> +</ul> +</li> +</ul> + + <h4>Previous topic</h4> + <p class="topless"><a href="ppapi-2.x.html" + title="previous chapter"><code class="docutils literal notranslate"><span class="pre">pplib</span></code> 2.x</a></p> + <h4>Next topic</h4> + <p class="topless"><a href="ppcode.html" + title="next chapter">Examples</a></p> + <div role="note" aria-label="source link"> + <h3>This Page</h3> + <ul class="this-page-menu"> + <li><a href="_sources/ppapi-1.x.rst.txt" + rel="nofollow">Show Source</a></li> + </ul> + </div> +<div id="searchbox" style="display: none" role="search"> + <h3>Quick search</h3> + <div class="searchformwrapper"> + <form class="search" action="search.html" method="get"> + <input type="text" name="q" /> + <input type="submit" value="Go" /> + <input type="hidden" name="check_keywords" value="yes" /> + <input type="hidden" name="area" value="default" /> + </form> + </div> +</div> +<script type="text/javascript">$('#searchbox').show(0);</script> + </div> + </div> + + <div class="document"> + <div class="documentwrapper"> + <div class="bodywrapper"> + <div class="body" role="main"> + + <div class="section" id="pplib-1-x"> +<h1><code class="docutils literal notranslate"><span class="pre">pplib</span></code> 1.x<a class="headerlink" href="#pplib-1-x" title="Permalink to this headline">¶</a></h1> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> is a library for raw PDF access. It parses PDF documents and provides an interface to access document structures in C.</p> +</div> +<div class="section" id="c-api"> +<h1>C-API<a class="headerlink" href="#c-api" title="Permalink to this headline">¶</a></h1> +<div class="section" id="types"> +<h2>Types<a class="headerlink" href="#types" title="Permalink to this headline">¶</a></h2> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> defines several C-types to represent PDF types:</p> +<ul class="simple"> +<li><code class="docutils literal notranslate"><span class="pre">ppint</span></code> - signed integer (<code class="docutils literal notranslate"><span class="pre">int64_t</span></code>)</li> +<li><code class="docutils literal notranslate"><span class="pre">ppnum</span></code> - real number (double)</li> +<li><code class="docutils literal notranslate"><span class="pre">ppname</span></code> - PDF name</li> +<li><code class="docutils literal notranslate"><span class="pre">ppstring</span></code> - PDF string</li> +<li><code class="docutils literal notranslate"><span class="pre">pparray</span></code> - PDF array</li> +<li><code class="docutils literal notranslate"><span class="pre">ppdict</span></code> - PDF dict</li> +<li><code class="docutils literal notranslate"><span class="pre">ppstream</span></code> - PDF stream</li> +<li><code class="docutils literal notranslate"><span class="pre">ppref</span></code> - PDF indirect reference</li> +<li><code class="docutils literal notranslate"><span class="pre">ppobj</span></code> - a container of all above</li> +</ul> +<p>Among <code class="docutils literal notranslate"><span class="pre">ppint</span></code> and <code class="docutils literal notranslate"><span class="pre">ppnum</span></code>, we also use <code class="docutils literal notranslate"><span class="pre">ppuint</span></code> - unsigned integer (machine word, alias to <code class="docutils literal notranslate"><span class="pre">size_t</span></code>).</p> +<p>Other API types:</p> +<ul class="simple"> +<li><code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> - PDF document</li> +<li><code class="docutils literal notranslate"><span class="pre">ppxref</span></code> - cross-references table</li> +<li><code class="docutils literal notranslate"><span class="pre">ppcontext</span></code> - … later</li> +<li><code class="docutils literal notranslate"><span class="pre">pprect</span></code> - rectangle</li> +<li><code class="docutils literal notranslate"><span class="pre">ppmatrix</span></code> - matrix</li> +</ul> +<p>Integer, number, name and string are treated as simple types. +Names and strings are actually C-structures, but exposed to API as typedefs to <code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*</span></code>. +Other types (array, dict, stream, reference, object container, xref, PDF) are C-structures, +and you operate it their pointers. So when you declare a simple type variable you say:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppuint</span> <span class="n">u</span><span class="p">;</span> +<span class="n">ppnum</span> <span class="n">n</span><span class="p">;</span> +<span class="n">ppname</span> <span class="n">name</span><span class="p">;</span> +<span class="n">ppstring</span> <span class="n">string</span><span class="p">;</span> +<span class="o">...</span> +</pre></div> +</div> +<p>And when you declare a compound type you operate on pointers:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span><span class="n">obj</span><span class="p">;</span> +<span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">;</span> +<span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">;</span> +<span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">;</span> +<span class="n">ppref</span> <span class="o">*</span><span class="n">ref</span><span class="p">;</span> +<span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">;</span> +</pre></div> +</div> +<p>Some of those C-types are defined in library header <code class="docutils literal notranslate"><span class="pre">ppapi.h</span></code> (complete types). Some others are incomplete +(eg. you can’t say <code class="docutils literal notranslate"><span class="pre">sizeof(ppdoc)</span></code> or <code class="docutils literal notranslate"><span class="pre">sizeof(ppxref)</span></code>). This is to avoid unnecesary dependencies in +the header. [At some points it’s not clear to me what to hide and what to expose, will see.] The library itself +uses <code class="docutils literal notranslate"><span class="pre">pplib.h</span></code> but for auxilary applications including a standalone <code class="docutils literal notranslate"><span class="pre">ppapi.h</span></code> header should be enough.</p> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> was designed having <strong>read-only</strong> PDF access in mind. Even if some structure is completelly exposed, +so that you can directly access its members, you should treat them as read-only. I don’t make them <code class="docutils literal notranslate"><span class="pre">const</span></code> because +then all variable declarations would need to be <code class="docutils literal notranslate"><span class="pre">const</span></code>, which is annoying, and I’d need some trickery in the library +internals to unconst. Besides, nothing is really const for C type casts.</p> +</div> +<div class="section" id="object"> +<h2>Object<a class="headerlink" href="#object" title="Permalink to this headline">¶</a></h2> +<p>A common container for all elementary PDF object types is <code class="docutils literal notranslate"><span class="pre">ppobj</span></code> structure. <code class="docutils literal notranslate"><span class="pre">ppobj</span></code> has a type identifier +(integer) and union of values:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">struct</span> <span class="n">ppobj</span> <span class="p">{</span> + <span class="n">ppobjtp</span> <span class="nb">type</span><span class="p">;</span> + <span class="n">union</span> <span class="p">{</span> + <span class="n">ppint</span> <span class="n">integer</span><span class="p">;</span> + <span class="n">ppnum</span> <span class="n">number</span><span class="p">;</span> + <span class="n">ppname</span> <span class="n">name</span><span class="p">;</span> + <span class="n">ppstring</span> <span class="n">string</span><span class="p">;</span> + <span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">;</span> + <span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">;</span> + <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">;</span> + <span class="n">ppref</span> <span class="o">*</span><span class="n">ref</span><span class="p">;</span> + <span class="n">void</span> <span class="o">*</span><span class="nb">any</span><span class="p">;</span> + <span class="p">};</span> +<span class="p">};</span> +</pre></div> +</div> +<p>Object type is one of constants (enum):</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PPNONE</span> +<span class="n">PPNULL</span> +<span class="n">PPBOOL</span> +<span class="n">PPINT</span> +<span class="n">PPNUM</span> +<span class="n">PPNAME</span> +<span class="n">PPSTRING</span> +<span class="n">PPARRAY</span> +<span class="n">PPDICT</span> +<span class="n">PPSTREAM</span> +<span class="n">PPREF</span> +</pre></div> +</div> +<p>The type determines the structure member you’re allowed to access:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span><span class="n">obj</span><span class="p">;</span> +<span class="o">...</span> +<span class="n">switch</span> <span class="p">(</span><span class="n">obj</span><span class="o">-></span><span class="nb">type</span><span class="p">)</span> +<span class="p">{</span> + <span class="n">case</span> <span class="n">PPNONE</span><span class="p">:</span> <span class="o">//</span> <span class="n">shouldn</span><span class="s1">'t actually happen, indicates some failure</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPNULL</span><span class="p">:</span> <span class="o">//</span> <span class="n">valid</span> <span class="n">PDF</span> <span class="n">null</span> <span class="nb">object</span><span class="p">,</span> <span class="n">no</span> <span class="n">value</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPBOOL</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">integer</span> <span class="p">(</span><span class="n">ppint</span><span class="p">),</span> <span class="n">value</span> <span class="mi">0</span> <span class="ow">or</span> <span class="mi">1</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPINT</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">integer</span> <span class="p">(</span><span class="n">ppint</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPNUM</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">number</span> <span class="p">(</span><span class="n">ppnum</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPNAME</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">name</span> <span class="p">(</span><span class="n">ppname</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPSTRING</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">string</span> <span class="p">(</span><span class="n">ppstring</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPARRAY</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">array</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPDICT</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="nb">dict</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPSTREAM</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">stream</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPREF</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">ref</span> <span class="p">(</span><span class="n">ppref</span> <span class="o">*</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> +<span class="p">}</span> +</pre></div> +</div> +<p>More often then not you know exactly what type of object value is expected, in which case +you may use one of the following macros:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">//</span> <span class="n">returns</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPNULL</span> +<span class="nb">int</span> <span class="n">ppobj_get_null</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> \ + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPBOOL</span><span class="p">,</span> <span class="n">sets</span> <span class="nb">int</span> <span class="n">v</span> <span class="n">to</span> <span class="mi">0</span> <span class="ow">or</span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">returns</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span> <span class="n">otherwise</span> +<span class="nb">int</span> <span class="n">ppobj_get_bool</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPINT</span><span class="p">,</span> <span class="n">sets</span> <span class="n">ppint</span> <span class="n">v</span> <span class="ow">and</span> <span class="n">returns</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span> <span class="n">otherwise</span> +<span class="nb">int</span> <span class="n">ppobj_get_int</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPINT</span> <span class="ow">and</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">sets</span> <span class="n">ppuint</span> <span class="n">v</span> <span class="ow">and</span> <span class="n">returns</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span> <span class="n">otherwise</span> +<span class="nb">int</span> <span class="n">ppobj_get_uint</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPNUM</span> <span class="ow">or</span> <span class="n">PPINT</span><span class="p">,</span> <span class="n">sets</span> <span class="n">ppnum</span> <span class="n">v</span> <span class="ow">and</span> <span class="n">returns</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span> <span class="n">otherwise</span> +<span class="nb">int</span> <span class="n">ppobj_get_num</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPNAME</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">name</span><span class="p">,</span> <span class="n">NULL</span> <span class="n">otherwise</span> +<span class="n">ppname</span> <span class="n">ppobj_get_name</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPSTRING</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">string</span><span class="p">,</span> <span class="n">NULL</span> <span class="n">otherwise</span> +<span class="n">ppstring</span> <span class="n">ppobj_get_string</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPARRAY</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">array</span><span class="p">,</span> <span class="n">NULL</span> <span class="n">otherwise</span> +<span class="n">pparray</span> <span class="o">*</span> <span class="n">ppobj_get_array</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPDICT</span> <span class="n">returns</span> <span class="n">the</span> <span class="nb">dict</span><span class="p">,</span> <span class="n">NULL</span> <span class="n">otherwise</span> +<span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppobj_get_dict</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPSTREAM</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">stream</span><span class="p">,</span> <span class="n">NULL</span> <span class="n">otherwise</span> +<span class="n">ppstream</span> <span class="o">*</span> <span class="n">ppobj_get_stream</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPREF</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">reference</span><span class="p">,</span> <span class="n">NULL</span> <span class="n">otherwise</span> +<span class="n">ppref</span> <span class="o">*</span> <span class="n">ppobj_get_ref</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> +</pre></div> +</div> +<p>Note the coercion from integer to real number, but not reverse. In practise, whenever you expect a real number, +you should also handle integer (eg. ‘1’ used instead of ‘1.0’).</p> +<p>It is a common case that the object is given as an indirect reference, but what you actually +want is not the reference, but the object referred by it. Here is a helper for it:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPREF</span><span class="p">,</span> <span class="n">returns</span> <span class="n">what</span> <span class="n">the</span> <span class="n">reference</span> <span class="n">points</span><span class="p">,</span> <span class="n">otherwise</span> <span class="n">returns</span> <span class="n">o</span> +<span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppobj_rget_obj</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> +</pre></div> +</div> +<p>Also every <code class="docutils literal notranslate"><span class="pre">ppobj_get_*</span></code> macro has <code class="docutils literal notranslate"><span class="pre">ppobj_rget_*</span></code> counterpart that makes a check +for the expected type, but if the object is PPREF, it jumps to the target object. +So for example <code class="docutils literal notranslate"><span class="pre">ppobj_rget_dict(obj)</span></code> will return dict if <code class="docutils literal notranslate"><span class="pre">obj</span></code> is of type PPDICT +or if it is of type PPREF and <code class="docutils literal notranslate"><span class="pre">obj->ref</span></code> hosts an object of type PPDICT.</p> +</div> +<div class="section" id="names"> +<h2>Names<a class="headerlink" href="#names" title="Permalink to this headline">¶</a></h2> +<p>PDF names are represented as <code class="docutils literal notranslate"><span class="pre">ppname</span></code>. +I find it convenient to have <code class="docutils literal notranslate"><span class="pre">ppname</span></code> type pretending <code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*</span></code>. This allows to use <code class="docutils literal notranslate"><span class="pre">ppname</span></code> +in all C-style string functions like <code class="docutils literal notranslate"><span class="pre">printf("%s",</span> <span class="pre">name)</span></code>.</p> +<p>Be aware, however, that <code class="docutils literal notranslate"><span class="pre">ppname</span></code> is actually a C-structure. It is perfectly ok to cast <code class="docutils literal notranslate"><span class="pre">ppname</span></code> to <code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*</span></code>:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppname</span> <span class="n">name</span><span class="p">;</span> +<span class="o">...</span> +<span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="p">)</span><span class="n">name</span><span class="p">;</span> +</pre></div> +</div> +<p>But reverse is forbidden:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">cstr</span> <span class="o">=</span> <span class="s2">"cstring"</span><span class="p">;</span> +<span class="o">...</span> +<span class="p">(</span><span class="n">ppname</span><span class="p">)</span><span class="n">cstr</span><span class="p">;</span> <span class="o">//</span> <span class="n">expect</span> <span class="n">segmentation</span> <span class="n">fault</span> <span class="n">soon</span> +</pre></div> +</div> +<p>For convenient use in C, names are <code class="docutils literal notranslate"><span class="pre">'\0'</span></code> terminated. But to get the length of name better always use +<code class="docutils literal notranslate"><span class="pre">ppname_size()</span></code> macro. <code class="docutils literal notranslate"><span class="pre">ppname</span></code> object knows its size, don’t use <code class="docutils literal notranslate"><span class="pre">strlen()</span></code>:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">size_t</span> <span class="n">ppname_size</span><span class="p">(</span><span class="n">ppname</span> <span class="n">name</span><span class="p">);</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">length</span> <span class="n">of</span> <span class="n">name</span> <span class="ow">in</span> <span class="nb">bytes</span> +</pre></div> +</div> +<p>In current implementation names are not hashed anyhow, so name-to-name comparison is not smarter than <code class="docutils literal notranslate"><span class="pre">memcmp()</span></code>. +Use macros:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">ppname_is</span><span class="p">(</span><span class="n">ppname</span> <span class="n">name</span><span class="p">,</span> <span class="s2">"literal"</span><span class="p">);</span> <span class="o">//</span> <span class="n">to</span> <span class="n">compare</span> <span class="n">ppname</span> <span class="k">with</span> <span class="n">C</span><span class="o">-</span><span class="n">literal</span> <span class="n">string</span> +<span class="nb">int</span> <span class="n">ppname_eq</span><span class="p">(</span><span class="n">ppname</span> <span class="n">name</span><span class="p">,</span> <span class="n">ppname</span> <span class="n">other</span><span class="p">);</span> <span class="o">//</span> <span class="n">to</span> <span class="n">compare</span> <span class="n">ppname</span> <span class="k">with</span> <span class="n">a</span> <span class="n">different</span> <span class="n">name</span> +</pre></div> +</div> +<p>If you’ll use <code class="docutils literal notranslate"><span class="pre">pplib</span></code> to parse contents streams, you may need to distinguish names from operators +(more precisely executable names). Names in PDF are preceeded by ‘/’, executable names aren’t. In both +cases PDF parser will produce <code class="docutils literal notranslate"><span class="pre">ppname</span></code> but can be distingushed with:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">ppname_exec</span><span class="p">(</span><span class="n">ppname</span> <span class="n">name</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">non</span><span class="o">-</span><span class="n">zero</span> <span class="k">if</span> <span class="n">name</span> <span class="ow">is</span> <span class="n">executable</span> +</pre></div> +</div> +<p>Names are kept in their raw form, with possible PDF specific escapes (in text below we call it <strong>encoded</strong> form). +Leading ‘/’ is omitted, though. One may need a decoded name, with no PDF escapes. +A pair of functions provides a simple interface to switch between those two forms:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppname</span> <span class="n">ppname_decoded</span> <span class="p">(</span><span class="n">ppname</span> <span class="n">name</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">decoded</span> <span class="p">(</span><span class="n">unescaped</span><span class="p">)</span> <span class="n">form</span> <span class="n">of</span> <span class="n">the</span> <span class="n">name</span> +<span class="n">ppname</span> <span class="n">ppname_encoded</span> <span class="p">(</span><span class="n">ppname</span> <span class="n">name</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">encoded</span> <span class="p">(</span><span class="n">escaped</span><span class="p">)</span> <span class="n">form</span> <span class="n">of</span> <span class="n">the</span> <span class="n">name</span> +</pre></div> +</div> +<p>In pretty most cases PDF names contains only letters (no special characters, no escapes), so decoded and encoded forms are identical. +In that case both functions simply return the argument. It is ok to call <code class="docutils literal notranslate"><span class="pre">ppname_decoded()</span></code> on already decoded form +and <code class="docutils literal notranslate"><span class="pre">ppname_encoded()</span></code> on already encoded form. Both forms are produced by PDF objects parser, so accessing <code class="docutils literal notranslate"><span class="pre">ppname</span></code> alter ego +in whatever direction needs no extra decoding or allocation costs.</p> +</div> +<div class="section" id="string"> +<h2>String<a class="headerlink" href="#string" title="Permalink to this headline">¶</a></h2> +<p>PDF strings have the same internal construction as names, so most of names description above applies to strings as well. +<code class="docutils literal notranslate"><span class="pre">ppstring</span></code> is a typedef of <code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*</span></code>, roughly <code class="docutils literal notranslate"><span class="pre">'\0'</span></code> terminiated C-string. To get the size of the string:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">size_t</span> <span class="n">ppstring_size</span><span class="p">(</span><span class="n">ppstring</span> <span class="n">string</span><span class="p">);</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">length</span> <span class="n">of</span> <span class="n">the</span> <span class="n">string</span> <span class="ow">in</span> <span class="nb">bytes</span> +</pre></div> +</div> +<p>Strings are provided in their raw form, preserving PDF specific escapes, but with no +<code class="docutils literal notranslate"><span class="pre">()</span></code> or <code class="docutils literal notranslate"><span class="pre"><></span></code> delims. To distinguish plain strings from hex strings:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">ppstring_hex</span><span class="p">(</span><span class="n">ppstring</span> <span class="n">string</span><span class="p">);</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">non</span> <span class="n">zero</span> <span class="k">if</span> <span class="nb">hex</span> <span class="n">string</span> +</pre></div> +</div> +<p>Or if you prefer:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>switch (ppstring_type(string)) +{ + case PPSTRING_PLAIN: // literal string, surrounded by ``(`` and ``)`` in PDF + break; + case PPSTRING_BASE16: // hex string, surrounded by ``<`` and ``>`` in PDF + break; + case PPSTRING_BASE85: // base85 string surrounded by ``<~`` and ``~>`` in PDF + break; +} +</pre></div> +</div> +<p>The last is actually Postscript specific, not used in PDF, but I think it might appear in contents streams… +No matter how the string is given in PDF (plain or hex), here are two functions to +switch between encoded and decoded strings forms:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstring</span> <span class="n">ppstring_decoded</span> <span class="p">(</span><span class="n">ppstring</span> <span class="n">string</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">decoded</span> <span class="n">string</span> <span class="n">possibly</span> <span class="k">with</span> <span class="n">PDF</span> <span class="n">escapes</span> +<span class="n">ppstring</span> <span class="n">ppstring_encoded</span> <span class="p">(</span><span class="n">ppstring</span> <span class="n">string</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">encoded</span> <span class="n">string</span> <span class="k">with</span> <span class="n">no</span> <span class="n">PDF</span> <span class="n">escapes</span> +</pre></div> +</div> +<p>For hex strings, encoded form contains hex digits, while decoded form contains arbitrary bytes (the result of hex decoding). +Plain strings usually contains printable ASCII characters, but they might contain any binary data. +As with names, objects parser produces both forms. The raw form with PDF escapes (or raw hex form) is considered the main one. +Eg. when you access <code class="docutils literal notranslate"><span class="pre">obj->string</span></code> you always get the encoded form. At any moment you can switch to its alter ego.</p> +<p>No matter if the string is plain or hex, if its first two bytes (decoded) are UTF16 BOM, the string +is considered unicode. <code class="docutils literal notranslate"><span class="pre">ppstring</span></code> object <em>knows</em> it is unicode or not:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">switch</span> <span class="p">(</span><span class="n">ppstring_utf</span><span class="p">(</span><span class="n">string</span><span class="p">))</span> +<span class="p">{</span> + <span class="n">case</span> <span class="n">PPSTRING_UTF16LE</span><span class="p">:</span> <span class="o">//</span> <span class="n">unicode</span> <span class="n">string</span><span class="p">,</span> <span class="n">utf16le</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPSTRING_UTF16BE</span><span class="p">:</span> <span class="o">//</span> <span class="n">unicode</span> <span class="n">string</span><span class="p">,</span> <span class="n">utf16be</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">default</span><span class="p">:</span> <span class="o">//</span> <span class="n">no</span> <span class="n">unicode</span> +<span class="p">}</span> +</pre></div> +</div> +<p>Or simply:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">ppstring_utf</span><span class="p">(</span><span class="n">string</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> + <span class="o">//</span> <span class="n">handle</span> <span class="n">unicode</span> <span class="n">string</span> +<span class="p">}</span> +</pre></div> +</div> +<p>If the string is unicode, BOM remains the part of the string – <code class="docutils literal notranslate"><span class="pre">pplib</span></code> parser does not strip it. +Unicode or not, encoded or decoded, strings are always C-arrays of bytes and <code class="docutils literal notranslate"><span class="pre">ppstring_size()</span></code> +always returns the size in bytes.</p> +</div> +<div class="section" id="array"> +<h2>Array<a class="headerlink" href="#array" title="Permalink to this headline">¶</a></h2> +<p>PDF arrays are represented as <code class="docutils literal notranslate"><span class="pre">pparray</span></code> type, which is C-array of <code class="docutils literal notranslate"><span class="pre">ppobj</span></code> structures. +To get the size:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">size_t</span> <span class="n">pparray_size</span><span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">number</span> <span class="n">of</span> <span class="n">array</span> <span class="n">items</span> +</pre></div> +</div> +<p>To get <code class="docutils literal notranslate"><span class="pre">ppobj</span> <span class="pre">*</span></code> at a given index:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span> <span class="n">pparray_at</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">ppobj</span> <span class="o">*</span> <span class="p">(</span><span class="n">no</span> <span class="n">index</span> <span class="n">check</span><span class="p">)</span> +<span class="n">ppobj</span> <span class="o">*</span> <span class="n">pparray_get</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">ppobj</span> <span class="o">*</span> <span class="ow">or</span> <span class="n">NULL</span> <span class="p">(</span><span class="k">with</span> <span class="n">index</span> <span class="n">check</span><span class="p">)</span> +<span class="n">ppobj</span> <span class="o">*</span> <span class="n">pparray_get_obj</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span> <span class="n">function</span> <span class="n">equiv</span> <span class="n">to</span> <span class="n">pparray_get</span><span class="p">()</span> +</pre></div> +</div> +<p>Iterating over array elements:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">;</span> +<span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +<span class="n">ppobj</span> <span class="o">*</span><span class="n">obj</span><span class="p">;</span> +<span class="k">for</span> <span class="p">(</span><span class="n">size</span> <span class="o">=</span> <span class="n">pparray_size</span><span class="p">(</span><span class="n">array</span><span class="p">),</span> <span class="n">pparray_first</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">index</span><span class="p">,</span> <span class="n">obj</span><span class="p">);</span> <span class="n">index</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="n">pparray_next</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">obj</span><span class="p">))</span> +<span class="p">{</span> + <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">index</span> <span class="ow">and</span> <span class="n">obj</span> +<span class="p">}</span> +</pre></div> +</div> +<p>There is no magic first/next macros, just iteration over pointers. One could also use something like:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="p">(</span><span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">size</span> <span class="o">=</span> <span class="n">array</span><span class="o">-></span><span class="n">size</span><span class="p">;</span> <span class="n">index</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="o">++</span><span class="n">index</span><span class="p">)</span> +<span class="p">{</span> + <span class="n">obj</span> <span class="o">=</span> <span class="n">pparray_at</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">index</span><span class="p">);</span> + <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">index</span> <span class="ow">and</span> <span class="n">obj</span> +<span class="p">}</span> +</pre></div> +</div> +<p>When getting values from array and expecting a result of known type, use one of the following:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">pparray_get_bool</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="nb">int</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">boolean</span> <span class="n">value</span> +<span class="nb">int</span> <span class="n">pparray_get_int</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">ppint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppint</span> <span class="n">value</span> +<span class="nb">int</span> <span class="n">pparray_get_uint</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">ppuint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppuint</span> <span class="n">value</span> +<span class="nb">int</span> <span class="n">pparray_get_num</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">ppnum</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppnum</span> <span class="n">value</span> +<span class="n">ppname</span> <span class="n">pparray_get_name</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppname</span> <span class="n">value</span> +<span class="n">ppstring</span> <span class="n">pparray_get_string</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppstring</span> <span class="n">value</span> +<span class="n">pparray</span> <span class="o">*</span> <span class="n">pparray_get_array</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">pparray</span> <span class="o">*</span> <span class="n">value</span> +<span class="n">ppdict</span> <span class="o">*</span> <span class="n">pparray_get_dict</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppdict</span> <span class="o">*</span> <span class="n">value</span> +<span class="n">ppref</span> <span class="o">*</span> <span class="n">pparray_get_ref</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppref</span> <span class="o">*</span> <span class="n">value</span> +</pre></div> +</div> +<p>As with <code class="docutils literal notranslate"><span class="pre">ppobj_get_*</span></code> suite, numeric types getters set the value of a given type and returns 1, if the type matches. +Otherwise sets nothing and returns 0. Other getters return the value if the type matches, or NULL.</p> +<p>Every function from <code class="docutils literal notranslate"><span class="pre">pparray_get_*</span></code> suite have its <code class="docutils literal notranslate"><span class="pre">pparray_rget_*</span></code> counterpart that +that dereferences indirect objects (as explained for <code class="docutils literal notranslate"><span class="pre">ppobj_rget_*</span></code> getters). Note that +there is no <code class="docutils literal notranslate"><span class="pre">pparray_get_stream()</span></code> function, as streams in PDF are always indirect. +To get the stream from array use:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream</span> <span class="o">*</span> <span class="n">pparray_rget_stream</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> +</pre></div> +</div> +</div> +<div class="section" id="dict"> +<h2>Dict<a class="headerlink" href="#dict" title="Permalink to this headline">¶</a></h2> +<p>PDF dicts are represented as <code class="docutils literal notranslate"><span class="pre">ppdict</span></code> structure, which is C-array of <code class="docutils literal notranslate"><span class="pre">ppobj</span></code> with parallel +C-array of <code class="docutils literal notranslate"><span class="pre">ppname</span></code> pointers. To get the size of a dict:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">size_t</span> <span class="n">ppdict_size</span><span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">number</span> <span class="n">of</span> <span class="n">key</span><span class="o">-</span><span class="n">val</span> <span class="n">pairs</span> +</pre></div> +</div> +<p>To get the value at a given index (integer):</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppdict_at</span><span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">no</span> <span class="n">index</span> <span class="n">check</span> +</pre></div> +</div> +<p>To get the name (key) at a given index:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppname</span> <span class="n">ppdict_key</span><span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">no</span> <span class="n">index</span> <span class="n">check</span> +</pre></div> +</div> +<p>To iterate over dict key-val pairs:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">;</span> +<span class="n">ppname</span> <span class="o">*</span><span class="n">pkey</span><span class="p">;</span> +<span class="n">ppobj</span> <span class="o">*</span><span class="n">obj</span><span class="p">;</span> + +<span class="k">for</span> <span class="p">(</span><span class="n">ppdict_first</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">pkey</span><span class="p">,</span> <span class="n">obj</span><span class="p">);</span> <span class="o">*</span><span class="n">pkey</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">;</span> <span class="n">ppdict_next</span><span class="p">(</span><span class="n">pkey</span><span class="p">,</span> <span class="n">obj</span><span class="p">))</span> +<span class="p">{</span> + <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="o">*</span><span class="n">pkey</span> <span class="ow">and</span> <span class="n">obj</span> +<span class="p">}</span> +</pre></div> +</div> +<p>There is no magic in first/next macros, just iteration through keys and values lists pointers. +For convenient iteration, a list of keys is terminated with NULL, so in the code above <code class="docutils literal notranslate"><span class="pre">*pkey</span> <span class="pre">!=</span> <span class="pre">NULL</span></code> +is used as the loop condition. One may also iterate via indices:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">;</span> +<span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +<span class="n">ppname</span> <span class="n">key</span><span class="p">;</span> +<span class="n">ppobj</span> <span class="o">*</span><span class="n">obj</span><span class="p">;</span> +<span class="k">for</span> <span class="p">(</span><span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">size</span> <span class="o">=</span> <span class="n">ppdict_size</span><span class="p">(</span><span class="nb">dict</span><span class="p">);</span> <span class="n">index</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="o">++</span><span class="n">index</span><span class="p">)</span> +<span class="p">{</span> + <span class="n">key</span> <span class="o">=</span> <span class="n">ppdict_key</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">index</span><span class="p">);</span> + <span class="n">obj</span> <span class="o">=</span> <span class="n">ppdict_at</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">index</span><span class="p">);</span> + <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">key</span> <span class="ow">and</span> <span class="n">obj</span> +<span class="p">}</span> +</pre></div> +</div> +<p>To get the object associated with a given name, use one of the following:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppdict_get_obj</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="nb">int</span> <span class="n">ppdict_get_bool</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="nb">int</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> +<span class="nb">int</span> <span class="n">ppdict_get_int</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> +<span class="nb">int</span> <span class="n">ppdict_get_uint</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppuint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> +<span class="nb">int</span> <span class="n">ppdict_get_num</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppnum</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> +<span class="n">ppname</span> <span class="n">ppdict_get_name</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">ppstring</span> <span class="n">ppdict_get_string</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">pparray</span> <span class="o">*</span> <span class="n">ppdict_get_array</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppdict_get_dict</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">ppref</span> <span class="o">*</span> <span class="n">ppdict_get_ref</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +</pre></div> +</div> +<p>Note that all getters accepts <code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*</span></code> as key, so it is ok to say:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdict_rget_dict</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="s2">"Resources"</span><span class="p">);</span> +</pre></div> +</div> +<p>as well as:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdic_rget_dict</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">name</span><span class="p">);</span> <span class="o">//</span> <span class="n">ppname</span> <span class="n">name</span> +</pre></div> +</div> +<p>Every <code class="docutils literal notranslate"><span class="pre">ppdict_get_*</span></code> getter has <code class="docutils literal notranslate"><span class="pre">ppdict_rget_*</span></code> counterpart that dereferences +indirect objects if necessary. Note that there is no <code class="docutils literal notranslate"><span class="pre">ppdict_get_stream()</span></code> function, +but there is:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream</span> <span class="o">*</span> <span class="n">ppdict_rget_stream</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +</pre></div> +</div> +<p>So far dicts comes with no names mapping, so by-name dict accessors perform a linear search +through the keys list. PDF dicts are usually small, so it is fast enough. +Building names lookup for every dict in PDF makes no sense I think, as <code class="docutils literal notranslate"><span class="pre">pplib</span></code> applications +will query just several dicts I guess.. However, some apps may extensively query +resources, which may refer to hundreds of objects (eg. images). So some mapping for dicts +is still considered.</p> +</div> +<div class="section" id="stream"> +<h2>Stream<a class="headerlink" href="#stream" title="Permalink to this headline">¶</a></h2> +<p>PDF streams are represented as <code class="docutils literal notranslate"><span class="pre">ppstream</span></code> objects. To get the stream dict:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppstream_dict</span><span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span> +</pre></div> +</div> +<p>To read the stream data:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">uint8_t</span> <span class="o">*</span> <span class="n">ppstream_first</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">size</span><span class="p">,</span> <span class="nb">int</span> <span class="n">decode</span><span class="p">);</span> +<span class="n">uint8_t</span> <span class="o">*</span> <span class="n">ppstream_next</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">size</span><span class="p">);</span> +<span class="n">void</span> <span class="n">ppstream_done</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">);</span> +</pre></div> +</div> +<p>Both <code class="docutils literal notranslate"><span class="pre">first`</span> <span class="pre">and</span> <span class="pre">``next</span></code> functions return a chunk of stream data and sets the <code class="docutils literal notranslate"><span class="pre">size</span></code> of the chunk. +<code class="docutils literal notranslate"><span class="pre">decode</span></code> parameter tell the reader to decompress the stream (1) or return raw (0). A call to <code class="docutils literal notranslate"><span class="pre">ppstream_next()</span></code> +must be preceeded by <code class="docutils literal notranslate"><span class="pre">ppstream_first()</span></code>. Once you’re done with the stream, you have to call <code class="docutils literal notranslate"><span class="pre">ppstream_done()</span></code>, +no matter if the stream has been read to the end or not. The stream data iterator in use:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">uint8_t</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span> +<span class="n">size_t</span> <span class="n">size</span><span class="p">;</span> +<span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">;</span> +<span class="nb">int</span> <span class="n">decode</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="o">//</span> <span class="mi">1</span> <span class="o">-</span> <span class="n">get</span> <span class="n">decompressed</span><span class="p">,</span> <span class="mi">0</span> <span class="o">-</span> <span class="n">get</span> <span class="n">raw</span> + +<span class="k">for</span> <span class="p">(</span><span class="n">data</span> <span class="o">=</span> <span class="n">ppstream_first</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="n">decode</span><span class="p">);</span> <span class="n">data</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">;</span> <span class="n">data</span> <span class="o">=</span> <span class="n">ppstream_next</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">))</span> +<span class="p">{</span> + <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">data</span> <span class="ow">and</span> <span class="n">its</span> <span class="n">size</span> +<span class="p">}</span> +<span class="n">ppstream_done</span><span class="p">(</span><span class="n">stream</span><span class="p">);</span> +</pre></div> +</div> +<p>Every subsequent iterator call invalidates the previous reader output, so you have to utilize the returned chunk +of data just after you ot that. So the following is wrong:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">data1</span> <span class="o">=</span> <span class="n">ppstream_first</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> +<span class="n">data2</span> <span class="o">=</span> <span class="n">ppstream_next</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">);</span> +<span class="n">data3</span> <span class="o">=</span> <span class="n">ppstream_next</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">);</span> +<span class="n">some_output</span><span class="p">(</span><span class="n">data1</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span> +<span class="n">some_output</span><span class="p">(</span><span class="n">data2</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span> +</pre></div> +</div> +<p>The reader calls usually return the same pointer to internal buffer, just filled with a different data. +<code class="docutils literal notranslate"><span class="pre">pplib</span></code> allocates reasonably large buffer and fills that buffer on subsequent calls to the reader.</p> +<p>If the source stream has no compression, using both <code class="docutils literal notranslate"><span class="pre">decode</span> <span class="pre">==</span> <span class="pre">1</span></code> and <code class="docutils literal notranslate"><span class="pre">decode</span> <span class="pre">==</span> <span class="pre">0</span></code> should give the same result. +You can check if the stream is actually compressed with:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream_compressed</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">non</span> <span class="n">zero</span> <span class="k">if</span> <span class="o">/</span><span class="n">Filter</span> <span class="ow">is</span> <span class="n">present</span> +</pre></div> +</div> +<p>It might be necessary to load the entire stream data at once:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">uint8_t</span> <span class="o">*</span> <span class="n">ppstream_all</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">size</span><span class="p">,</span> <span class="nb">int</span> <span class="n">decode</span><span class="p">);</span> +</pre></div> +</div> +<p>If the initial buffer size is insufficient, it grows until the entire stream data is loaded. You must call +<code class="docutils literal notranslate"><span class="pre">ppstream_done(stream)</span></code> after using returned data.</p> +<p><code class="docutils literal notranslate"><span class="pre">ppstream_done()</span></code> doesn’t invalidate the stream object, it just closes its internal reader. +The stream itself remains a valid object (eg. one can read it again if necessary), +but the reader buffer is released. It is actually not freed but kept for future the reuse with that on some other stream, +but you still need to mark it ready for reuse to avoid allocating a separate buffer for every stream you’re going to read.</p> +<p>Stream data readers will return <code class="docutils literal notranslate"><span class="pre">NULL</span></code> if you haven’t close the previous reader process with <code class="docutils literal notranslate"><span class="pre">ppstream_done()</span></code>. All below is wrong:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">data1</span> <span class="o">=</span> <span class="n">ppstream_all</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> +<span class="n">data2</span> <span class="o">=</span> <span class="n">ppstream_all</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="o">//</span> <span class="n">data2</span> <span class="o">==</span> <span class="n">NULL</span> +<span class="o">//</span> <span class="ow">or</span> +<span class="n">data1</span> <span class="o">=</span> <span class="n">ppstream_first</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> +<span class="n">data2</span> <span class="o">=</span> <span class="n">ppstream_first</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="o">//</span> <span class="n">data2</span> <span class="o">==</span> <span class="n">NULL</span> +<span class="o">//</span> <span class="ow">or</span> +<span class="n">data1</span> <span class="o">=</span> <span class="n">ppstream_first</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> +<span class="n">data2</span> <span class="o">=</span> <span class="n">ppstream_all</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="o">//</span> <span class="n">data2</span> <span class="o">==</span> <span class="n">NULL</span> +</pre></div> +</div> +<p>To avoid unnecessary dependencies, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> does not support image filters (<code class="docutils literal notranslate"><span class="pre">/DCT</span></code>, <code class="docutils literal notranslate"><span class="pre">/JPX</span></code>, <code class="docutils literal notranslate"><span class="pre">/JBIG</span></code>, <code class="docutils literal notranslate"><span class="pre">/CCITT</span></code>). +But it is ok to read the stream with <code class="docutils literal notranslate"><span class="pre">decode</span></code> set to 1 on such streams. <code class="docutils literal notranslate"><span class="pre">pplib</span></code> assumes that the image is the +final/target stream form and just returns it as-is. Eg. in the case of JPEG (<code class="docutils literal notranslate"><span class="pre">/DCT</span></code> filtered) image both calls should +give the same results:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream_all</span><span class="p">(</span><span class="n">jpegstream</span><span class="p">,</span> <span class="o">&</span><span class="n">jpegsize</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="o">//</span> <span class="n">don</span><span class="s1">'t decode, return what'</span><span class="n">s</span> <span class="n">there</span> +<span class="n">ppstream_all</span><span class="p">(</span><span class="n">jpegstream</span><span class="p">,</span> <span class="o">&</span><span class="n">jpegsize</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="o">//</span> <span class="n">decode</span> <span class="n">but</span> <span class="n">found</span> <span class="n">image</span> <span class="nb">filter</span><span class="p">,</span> <span class="n">effectively</span> <span class="n">the</span> <span class="n">same</span> +</pre></div> +</div> +<p>A bit more about streams memory. As mentioned, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> allocates buffers for stream readers. After <code class="docutils literal notranslate"><span class="pre">ppstream_done()</span></code>, +the stream no longer <em>owns</em> the buffer space. But the buffer may remain allocated, to be reused with future readers. +<code class="docutils literal notranslate"><span class="pre">pplib</span></code> keeps a pool of several buffers. This means, that when you use stream readers, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> eats +some memory (1MB or so) that is not freed, even if no streams are used. And even if you free all objects. +If you suffer from this, you can optionally use a pair of functions:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">ppstream_init_buffers</span> <span class="p">(</span><span class="n">void</span><span class="p">);</span> +<span class="n">void</span> <span class="n">ppstream_free_buffers</span> <span class="p">(</span><span class="n">void</span><span class="p">);</span> +</pre></div> +</div> +<p>The first initializes buffers pool, unless done so far. Currently <code class="docutils literal notranslate"><span class="pre">pplib</span></code> cares of it before opening every stream reader, +so it is not obligatory. The second frees a pool of buffers. The intended use is to call <code class="docutils literal notranslate"><span class="pre">ppstream_init_buffers()</span></code> once +as kind of library initializer and to call <code class="docutils literal notranslate"><span class="pre">ppstream_free_buffers()</span></code> once, as the library finalizer.</p> +</div> +<div class="section" id="filters"> +<h2>Filters<a class="headerlink" href="#filters" title="Permalink to this headline">¶</a></h2> +<p>In version v1.00 (20190916) <code class="docutils literal notranslate"><span class="pre">ppstream</span></code> API has been extended with filters information. +<code class="docutils literal notranslate"><span class="pre">ppstream</span></code> knows its filter(s) and keps it as <code class="docutils literal notranslate"><span class="pre">stream->filter</span></code>:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">//</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">;</span> +<span class="n">ppstream_filter</span> <span class="o">*</span><span class="n">info</span> <span class="o">=</span> <span class="o">&</span><span class="n">stream</span><span class="o">-></span><span class="nb">filter</span><span class="p">;</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">ppstream_filter</span></code> is the following structure:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span> + <span class="n">ppstreamtp</span> <span class="o">*</span><span class="n">filters</span><span class="p">;</span> <span class="o">//</span> <span class="n">c</span><span class="o">-</span><span class="n">array</span> <span class="n">of</span> <span class="nb">filter</span> <span class="n">identifiers</span> <span class="p">(</span><span class="n">enum</span> <span class="n">integers</span><span class="p">)</span> + <span class="n">ppdict</span> <span class="o">**</span><span class="n">params</span><span class="p">;</span> <span class="o">//</span> <span class="n">c</span><span class="o">-</span><span class="n">array</span> <span class="n">of</span> <span class="n">ppdict</span> <span class="n">pointers</span> + <span class="n">size_t</span> <span class="n">count</span><span class="p">;</span> <span class="o">//</span> <span class="n">number</span> <span class="n">of</span> <span class="n">filters</span><span class="p">,</span> <span class="n">length</span> <span class="n">of</span> <span class="n">the</span> <span class="n">arrays</span> <span class="p">(</span><span class="n">typically</span> <span class="mi">1</span><span class="p">)</span> +<span class="p">}</span> <span class="n">ppstream_filter</span><span class="p">;</span> +</pre></div> +</div> +<p>If <code class="docutils literal notranslate"><span class="pre">count</span> <span class="pre">></span> <span class="pre">0</span></code> then <code class="docutils literal notranslate"><span class="pre">filters</span></code> member is not NULL. Filters array keeps integer constants:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PPSTREAM_BASE16</span> <span class="o">/*</span> <span class="o">/</span><span class="n">ASCIIHexDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_BASE85</span> <span class="o">/*</span> <span class="o">/</span><span class="n">ASCII85Decode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_RUNLENGTH</span> <span class="o">/*</span> <span class="o">/</span><span class="n">RunLengthDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_FLATE</span> <span class="o">/*</span> <span class="o">/</span><span class="n">FlateDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_LZW</span> <span class="o">/*</span> <span class="o">/</span><span class="n">LZWDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_CCITT</span> <span class="o">/*</span> <span class="o">/</span><span class="n">CCITTFaxDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_DCT</span> <span class="o">/*</span> <span class="o">/</span><span class="n">DCTDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_JBIG2</span> <span class="o">/*</span> <span class="o">/</span><span class="n">JBIG2Decode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_JPX</span> <span class="o">/*</span> <span class="o">/</span><span class="n">JPXDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_CRYPT</span> <span class="o">/*</span> <span class="o">/</span><span class="n">Crypt</span> <span class="o">*/</span> +</pre></div> +</div> +<p>Params array keeps corresponding filter parameters (<code class="docutils literal notranslate"><span class="pre">/DecodeParms</span></code>) if present. <code class="docutils literal notranslate"><span class="pre">params</span></code> member is not NULL +if <code class="docutils literal notranslate"><span class="pre">count</span> <span class="pre">></span> <span class="pre">0</span></code> and the stream dict has <code class="docutils literal notranslate"><span class="pre">/DecodeParms</span></code> entry. Even if <code class="docutils literal notranslate"><span class="pre">params</span></code> is there, +for every N-th filter, <code class="docutils literal notranslate"><span class="pre">params[N]</span></code> may be NULL (corresponding to PDF <code class="docutils literal notranslate"><span class="pre">null</span></code>).</p> +<p><code class="docutils literal notranslate"><span class="pre">stream->filter</span></code> keeps the source stream filter information, which may not correspond to the result of stream readers +(<code class="docutils literal notranslate"><span class="pre">ppstream_first()</span></code>, <code class="docutils literal notranslate"><span class="pre">ppstream_next()</span></code>, <code class="docutils literal notranslate"><span class="pre">ppstream_all()</span></code>). The get the filters info relevant to the result from readers:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">ppstream_filter_info</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">ppstream_filter</span> <span class="o">*</span><span class="n">info</span><span class="p">,</span> <span class="nb">int</span> <span class="n">decode</span><span class="p">);</span> +</pre></div> +</div> +<p>The function fills <code class="docutils literal notranslate"><span class="pre">ppstream_filter</span></code> structure according to the expected result from stream readers (example 3 shows +how to use it to reconstruct <code class="docutils literal notranslate"><span class="pre">/Filter</span></code> and <code class="docutils literal notranslate"><span class="pre">/DecodeParms</span></code> when copying the stream to some other PDF).</p> +<p>To convert filter identifier (<code class="docutils literal notranslate"><span class="pre">ppstreamtp</span></code>) to a corresponding PDF filter name:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">ppstream_filter_name</span><span class="p">[];</span> +</pre></div> +</div> +<p>To covert <code class="docutils literal notranslate"><span class="pre">ppname</span></code> to filter identifier:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">ppstream_filter_type</span> <span class="p">(</span><span class="n">ppname</span> <span class="n">filtername</span><span class="p">,</span> <span class="n">ppstreamtp</span> <span class="o">*</span><span class="n">filtertype</span><span class="p">);</span> +<span class="o">//</span> <span class="n">returns</span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">sets</span> <span class="n">filtertype</span> <span class="k">if</span> <span class="n">filtername</span> <span class="ow">is</span> <span class="n">the</span> <span class="n">proper</span> <span class="nb">filter</span> <span class="n">name</span> +</pre></div> +</div> +<p>Additional information about the stream can be fetched from macros:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream_compressed</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span> <span class="o">/*</span> <span class="n">stream</span><span class="o">-></span><span class="n">flags</span> <span class="o">&</span> <span class="p">(</span><span class="n">PPSTREAM_FILTER</span><span class="o">|</span><span class="n">PPSTREAM_IMAGE</span><span class="p">)</span> <span class="o">*/</span> +<span class="n">ppstream_filtered</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span> <span class="o">/*</span> <span class="n">stream</span><span class="o">-></span><span class="n">flags</span> <span class="o">&</span> <span class="n">PPSTREAM_FILTER</span> <span class="o">*/</span> +<span class="n">ppstream_image</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span> <span class="o">/*</span> <span class="n">stream</span><span class="o">-></span><span class="n">flags</span> <span class="o">*</span> <span class="n">PPSTREAM_IMAGE</span> <span class="o">*/</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">stream->flags</span></code> is a binary sum of the following:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PPSTREAM_FILTER</span> <span class="o">/*</span> <span class="nb">set</span> <span class="n">iff</span> <span class="n">the</span> <span class="n">stream</span> <span class="n">filters</span> <span class="nb">list</span> <span class="n">has</span> <span class="n">one</span> <span class="n">of</span><span class="p">:</span> <span class="n">BASE16</span><span class="p">,</span> <span class="n">BASE85</span><span class="p">,</span> <span class="n">RUNLENGTH</span><span class="p">,</span> <span class="n">FLATE</span><span class="p">,</span> <span class="n">LZW</span> <span class="o">*/</span> +<span class="n">PPSTREAM_IMAGE</span> <span class="o">/*</span> <span class="nb">set</span> <span class="n">iff</span> <span class="n">the</span> <span class="n">stream</span> <span class="n">filters</span> <span class="nb">list</span> <span class="n">has</span> <span class="n">one</span> <span class="n">of</span><span class="p">:</span> <span class="n">CCITT</span><span class="p">,</span> <span class="n">DCT</span><span class="p">,</span> <span class="n">JBIG2</span><span class="p">,</span> <span class="n">JPX</span> <span class="o">*/</span> +<span class="n">PPSTREAM_ENCRYPTED</span> <span class="o">/*</span> <span class="nb">set</span> <span class="n">iff</span> <span class="n">the</span> <span class="n">stream</span> <span class="ow">is</span> <span class="n">encrypted</span> <span class="o">*/</span> +<span class="n">PPSTREAM_ENCRYPTED_OWN</span> <span class="o">/*</span> <span class="nb">set</span> <span class="n">iff</span> <span class="n">the</span> <span class="n">stream</span> <span class="n">has</span> <span class="n">own</span> <span class="n">CRYPT</span> <span class="nb">filter</span> <span class="o">*/</span> +</pre></div> +</div> +<p>Note that <code class="docutils literal notranslate"><span class="pre">PPSTREAM_COMPRESSED</span></code> is not there any longer, use <code class="docutils literal notranslate"><span class="pre">ppstream_compressed()</span></code> instead. +And there is some more, see <code class="docutils literal notranslate"><span class="pre">ppapi.h</span></code>.</p> +</div> +<div class="section" id="ref"> +<h2>Ref<a class="headerlink" href="#ref" title="Permalink to this headline">¶</a></h2> +<p>Indirect objects are represented as <code class="docutils literal notranslate"><span class="pre">ppref</span></code> structure. To get the object that the +reference refers to:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppref_obj</span><span class="p">(</span><span class="n">ppref</span> <span class="o">*</span><span class="n">ref</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">ppref</span></code> structure also keeps the reference number and version, a pointer to cross reference table it belongs +to and others, but I guess you won’t need anything but the referenced object. <code class="docutils literal notranslate"><span class="pre">pplib</span></code> parser resolves references +on-fly. So if there is a dict with indirect objects:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o"><<</span> + <span class="o">/</span><span class="n">Type</span> <span class="o">/</span><span class="n">Page</span> + <span class="o">/</span><span class="n">Resources</span> <span class="mi">123</span> <span class="mi">0</span> <span class="n">R</span> + <span class="o">...</span> +<span class="o">>></span> +</pre></div> +</div> +<p>the parser will produce <code class="docutils literal notranslate"><span class="pre">ppdict</span></code> with <code class="docutils literal notranslate"><span class="pre">Resources</span></code> key pointing the proper <code class="docutils literal notranslate"><span class="pre">ppref</span> <span class="pre">*</span></code> value. +If you need more, access <code class="docutils literal notranslate"><span class="pre">ppref</span></code> members:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">struct</span> <span class="n">ppref</span> <span class="p">{</span> + <span class="n">ppobj</span> <span class="nb">object</span><span class="p">;</span> <span class="o">//</span> <span class="n">target</span> <span class="nb">object</span> + <span class="n">ppuint</span> <span class="n">number</span><span class="p">,</span> <span class="n">version</span><span class="p">;</span> <span class="o">//</span> <span class="n">identifiers</span> + <span class="n">size_t</span> <span class="n">offset</span><span class="p">;</span> <span class="o">//</span> <span class="n">file</span> <span class="n">offset</span> <span class="p">(</span><span class="n">useless</span> <span class="k">for</span> <span class="n">you</span><span class="p">,</span> <span class="n">may</span> <span class="n">be</span> <span class="n">zero</span> <span class="k">for</span> <span class="n">compressed</span> <span class="n">objects</span><span class="p">)</span> + <span class="n">ppuint</span> <span class="n">length</span><span class="p">;</span> <span class="o">//</span> <span class="n">the</span> <span class="n">length</span> <span class="n">of</span> <span class="n">the</span> <span class="n">original</span> <span class="nb">object</span> <span class="n">data</span> + <span class="n">ppxref</span> <span class="o">*</span><span class="n">xref</span><span class="p">;</span> <span class="o">//</span> <span class="n">cross</span> <span class="n">reference</span> <span class="n">table</span> <span class="n">it</span> <span class="n">belongs</span> <span class="n">to</span> +<span class="p">};</span> +</pre></div> +</div> +</div> +<div class="section" id="xref"> +<h2>XRef<a class="headerlink" href="#xref" title="Permalink to this headline">¶</a></h2> +<p>Cross reference table is exposed as <code class="docutils literal notranslate"><span class="pre">ppxref</span></code> (incomplete type, you can only oprate on its pointer). +To get top document xref:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppxref</span> <span class="o">*</span> <span class="n">ppdoc_xref</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>To get previous (older) xref:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppxref</span> <span class="o">*</span> <span class="n">ppxref_prev</span> <span class="p">(</span><span class="n">ppxref</span> <span class="o">*</span><span class="n">xref</span><span class="p">);</span> +</pre></div> +</div> +<p>To find an object of a given refnumber:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppref</span> <span class="o">*</span> <span class="n">ppxref_find</span> <span class="p">(</span><span class="n">ppxref</span> <span class="o">*</span><span class="n">xref</span><span class="p">,</span> <span class="n">ppuint</span> <span class="n">refnumber</span><span class="p">);</span> +</pre></div> +</div> +<p>[Note: since pplib v0.98 in case of documents with incremental update, <code class="docutils literal notranslate"><span class="pre">ppxref_find()</span></code> returns +the newest available version of a given object rather than the object in a given body.]</p> +</div> +<div class="section" id="pdf"> +<h2>PDF<a class="headerlink" href="#pdf" title="Permalink to this headline">¶</a></h2> +<p>PDF document is represented as <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> structure (incomplete type, you can only operate on its pointer). +To load a document from file:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdoc</span> <span class="o">*</span> <span class="n">ppdoc_load</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">filename</span><span class="p">);</span> +</pre></div> +</div> +<p>To load a document from memory data:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdoc</span> <span class="o">*</span> <span class="n">ppdoc_mem</span> <span class="p">(</span><span class="n">const</span> <span class="n">void</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">size</span><span class="p">);</span> +</pre></div> +</div> +<p>The data is assumed to be a buffer allocated with <code class="docutils literal notranslate"><span class="pre">malloc</span></code> - it is freed when destroying <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code>.</p> +<p>Both loaders returns <code class="docutils literal notranslate"><span class="pre">NULL</span></code> on failure.</p> +<p>To free <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> and all objects it refers to:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">ppdoc_free</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>So far we haven’t mention about any explicit object reclaimers. There are no dedicated <code class="docutils literal notranslate"><span class="pre">free</span></code> functions +for other objects. You don’t allocate or free objects yourself. <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> object is an owner of all +beings it refers to. It also means that every object described so far is alive as long as the containing +<code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> is alive.</p> +<p>To access main PDF dicts:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppdoc_trailer</span><span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">top</span> <span class="n">xref</span> <span class="n">trailer</span> <span class="nb">dict</span> +<span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppdoc_catalog</span><span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">catalog</span> <span class="n">referred</span> <span class="kn">from</span> <span class="nn">the</span> <span class="n">trailer</span> +<span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppdoc_info</span><span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">info</span> <span class="nb">dict</span> <span class="n">referred</span> <span class="kn">from</span> <span class="nn">the</span> <span class="n">trailer</span> +</pre></div> +</div> +<p>To get the PDF version:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">ppdoc_version_string</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> <span class="o">//</span> <span class="n">version</span> <span class="n">string</span> +<span class="nb">int</span> <span class="n">ppdoc_version_number</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">,</span> <span class="nb">int</span> <span class="o">*</span><span class="n">minor</span><span class="p">);</span> <span class="o">//</span> <span class="n">minor</span> <span class="ow">and</span> <span class="n">major</span> <span class="n">numbers</span> +</pre></div> +</div> +<p>To get the file size of the source PDF document:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">size_t</span> <span class="n">ppdoc_file_size</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>To get the number of objects in all xrefs:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppuint</span> <span class="n">ppdoc_objects</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>To get the approx usage of memory:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">size_t</span> <span class="n">ppdoc_memory</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">waste</span><span class="p">);</span> +</pre></div> +</div> +</div> +<div class="section" id="encryption"> +<h2>Encryption<a class="headerlink" href="#encryption" title="Permalink to this headline">¶</a></h2> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> handles encrypted (password protected) documents. If a document is encrypted, most of strings and streams are ciphered. +In that form they are unreadable and rather useless, you can’t even rewrite such strings/streams as-is to a different PDF output. +It is a common practise to <em>protect</em> documents with an empty password. Such documents remain readable in Acrobat (just opens them without prompting +for a password), but some features (eg. printing) may restricted by the application.</p> +<p>When <code class="docutils literal notranslate"><span class="pre">pplib</span></code> detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> proceeeds normally, providing +an access to decrypted strings and streams, as if they weren’t ciphered. If the document is protected with non-empty password, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> gives +a way to provide a password and proceed. Until you provide a password, <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> object returned by <code class="docutils literal notranslate"><span class="pre">ppdoc_load()</span></code> function has all object wntries +set to <code class="docutils literal notranslate"><span class="pre">null</span></code>.</p> +<p>After loading a document you should check encryption status with:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppcrypt_status</span> <span class="n">ppdoc_crypt_status</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">ppcrypt_status</span></code> (integer) may have the following values:</p> +<blockquote> +<div><code class="docutils literal notranslate"><span class="pre">PPCRYPT_NONE</span></code> - no encryption, go ahead +<code class="docutils literal notranslate"><span class="pre">PPCRYPT_DONE</span></code> - encryption present but password succeeded, go ahead +<code class="docutils literal notranslate"><span class="pre">PPCRYPT_PASS</span></code> - encryption present, need non-empty password +<code class="docutils literal notranslate"><span class="pre">PPCRYPT_FAIL</span></code> - invalid or unsupported encryption (eg. undocumented in pdf spec)</div></blockquote> +<p>If a password is needed, you can provide one with:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppcrypt_status</span> <span class="n">ppdoc_crypt_pass</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">,</span> <span class="n">const</span> <span class="n">void</span> <span class="o">*</span><span class="n">userpass</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">userpasslength</span><span class="p">,</span> + <span class="n">const</span> <span class="n">void</span> <span class="o">*</span><span class="n">ownerpass</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">ownerpasslength</span><span class="p">);</span> +</pre></div> +</div> +<p>Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough +to know that having one of them is enough to decrypt the document. If you know the password, you probably mean +<code class="docutils literal notranslate"><span class="pre">userpass</span></code>, in which case you should put <code class="docutils literal notranslate"><span class="pre">NULL</span></code> as <code class="docutils literal notranslate"><span class="pre">ownerpass</span></code>. The function returns <code class="docutils literal notranslate"><span class="pre">PPCRYPT_DONE</span></code> if the password +succeeds and the previous status otherwise. Your custom loader function may look like that:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">;</span> +<span class="n">pdf</span> <span class="o">=</span> <span class="n">ppdoc_load</span><span class="p">(</span><span class="s2">"file.pdf"</span><span class="p">);</span> +<span class="k">if</span> <span class="p">(</span><span class="n">pdf</span> <span class="o">==</span> <span class="n">NULL</span><span class="p">)</span> + <span class="k">return</span> <span class="n">NULL</span><span class="p">;</span> +<span class="n">switch</span> <span class="p">(</span><span class="n">ppdoc_crypt_status</span><span class="p">(</span><span class="n">pdf</span><span class="p">))</span> +<span class="p">{</span> + <span class="n">case</span> <span class="n">PPCRYPT_NONE</span><span class="p">:</span> + <span class="n">case</span> <span class="n">PPCRYPT_DONE</span><span class="p">:</span> + <span class="k">return</span> <span class="n">pdf</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPCRYPT_PASS</span><span class="p">:</span> + <span class="k">if</span> <span class="p">(</span><span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="s2">"dummy"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span> <span class="o">||</span> + <span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"dummy"</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span><span class="p">)</span> + <span class="k">return</span> <span class="n">pdf</span><span class="p">;</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">"sorry, password needed</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> + <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span> + <span class="k">return</span> <span class="n">NULL</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPCRYPT_FAIL</span><span class="p">:</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">"sorry, encryption failed</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> + <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span> + <span class="k">return</span> <span class="n">NULL</span><span class="p">;</span> +<span class="p">}</span> +</pre></div> +</div> +<p>[If you get <code class="docutils literal notranslate"><span class="pre">PPCRYPT_FAIL</span></code> it might mean <em>I failed</em>, so treat as a bug.]</p> +<p>If you’d like to know what permissions are given/restricted to encrypted document:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppint</span> <span class="n">ppdoc_permissions</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>Returned value can be queried with the following binary flags (you can verify with Acrobat <em>File -> Properties -> Security</em> tab):</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PPDOC_ALLOW_PRINT</span> <span class="o">//</span> <span class="n">printing</span> +<span class="n">PPDOC_ALLOW_MODIFY</span> <span class="o">//</span> <span class="n">filling</span> <span class="n">form</span> <span class="n">fields</span><span class="p">,</span> <span class="n">signing</span><span class="p">,</span> <span class="n">creating</span> <span class="n">template</span> <span class="n">pages</span> +<span class="n">PPDOC_ALLOW_COPY</span> <span class="o">//</span> <span class="n">copying</span><span class="p">,</span> <span class="n">copying</span> <span class="k">for</span> <span class="n">accessibility</span> +<span class="n">PPDOC_ALLOW_ANNOTS</span> <span class="o">//</span> <span class="n">filling</span> <span class="n">form</span> <span class="n">fields</span><span class="p">,</span> <span class="n">copying</span><span class="p">,</span> <span class="n">signing</span> +<span class="n">PPDOC_ALLOW_EXTRACT</span> <span class="o">//</span> <span class="n">contents</span> <span class="n">copying</span> <span class="k">for</span> <span class="n">accessibility</span> +<span class="n">PPDOC_ALLOW_ASSEMBLY</span> <span class="o">//</span> <span class="p">(</span><span class="n">no</span> <span class="n">effect</span><span class="p">)</span> +<span class="n">PPDOC_ALLOW_PRINT_HIRES</span> <span class="o">//</span> <span class="p">(</span><span class="n">no</span> <span class="n">effect</span><span class="p">)</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> does absolutelly nothing with permissions, it cares only to decrypt the document. As mentioned, encryption applies to strings +and streams. <code class="docutils literal notranslate"><span class="pre">pplib</span></code> decrypt strings when parsing document objects, so the result you get is <em>normal</em> (not ciphered). +Streams are decrypted whenever you access them. Even if you ask for a raw stream data, you’ll get a raw (compressed) stream, but decrypted. +So except the check to <code class="docutils literal notranslate"><span class="pre">ppdoc_crypt_status()</span></code>, you shouldn’t bother about encryption.</p> +<p>In encrypted documents most of streams are encrypted. To check if a given stream is encrypted:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream_encrypted</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">non</span><span class="o">-</span><span class="n">zero</span> <span class="k">if</span> <span class="n">encrypted</span> +</pre></div> +</div> +<p>Encryption is independent from compression, don’t confuse with <code class="docutils literal notranslate"><span class="pre">ppstream_compressed()</span></code></p> +</div> +<div class="section" id="pages"> +<h2>Pages<a class="headerlink" href="#pages" title="Permalink to this headline">¶</a></h2> +<p>Several helpers to deal with pages. To get the number of pages:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppuint</span> <span class="n">ppdoc_page_count</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>To access the root pages tree node:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppref</span> <span class="o">*</span> <span class="n">ppdoc_pages</span><span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>To get the page reference at a given index:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppref</span> <span class="o">*</span> <span class="n">ppdoc_page</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">,</span> <span class="n">ppuint</span> <span class="n">index</span><span class="p">);</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">index</span></code> is a page number. First page has number 1. For index out of bounds <code class="docutils literal notranslate"><span class="pre">ppdoc_page()</span></code> returns NULL. +Iterating over pages using index from 1 to <code class="docutils literal notranslate"><span class="pre">ppdoc_page_count()</span></code> and calling <code class="docutils literal notranslate"><span class="pre">ppdoc_page()</span></code> on each iteration +would be suboptimal. Here is a dedicted iterator for this:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppref</span> <span class="o">*</span> <span class="n">ppdoc_first_page</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +<span class="n">ppref</span> <span class="o">*</span> <span class="n">ppdoc_next_page</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>The iterator in use:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">;</span> +<span class="n">ppref</span> <span class="o">*</span><span class="n">ref</span><span class="p">;</span> +<span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">;</span> +<span class="nb">int</span> <span class="n">pageno</span><span class="p">;</span> + +<span class="n">pdf</span> <span class="o">=</span> <span class="n">ppdoc_load</span><span class="p">(</span><span class="s2">"file.pdf"</span><span class="p">);</span> +<span class="k">for</span> <span class="p">(</span><span class="n">ref</span> <span class="o">=</span> <span class="n">ppdoc_first_page</span><span class="p">(</span><span class="n">pdf</span><span class="p">),</span> <span class="n">pageno</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">ref</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">;</span> <span class="n">ref</span> <span class="o">=</span> <span class="n">ppdoc_next_page</span><span class="p">(</span><span class="n">pdf</span><span class="p">),</span> <span class="o">++</span><span class="n">pageno</span><span class="p">)</span> +<span class="p">{</span> + <span class="nb">dict</span> <span class="o">=</span> <span class="n">ppref_obj</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span><span class="o">-></span><span class="nb">dict</span><span class="p">;</span> <span class="o">//</span> <span class="n">take</span> <span class="k">for</span> <span class="n">granted</span> <span class="n">it</span> <span class="ow">is</span> <span class="n">a</span> <span class="nb">dict</span> + <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">the</span> <span class="n">page</span> <span class="nb">dict</span> +<span class="p">}</span> +</pre></div> +</div> +<p>Functions related to pages return <code class="docutils literal notranslate"><span class="pre">ppref</span> <span class="pre">*</span></code> ensured to contain dict object, so you don’t need sanity +type checks here.</p> +</div> +<div class="section" id="contents"> +<h2>Contents<a class="headerlink" href="#contents" title="Permalink to this headline">¶</a></h2> +<p>PDF page contents can be given as a stream or array of streams. Here is a convenience iterator over page +contents streams:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream</span> <span class="o">*</span> <span class="n">ppcontents_first</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">);</span> +<span class="n">ppstream</span> <span class="o">*</span> <span class="n">ppcontents_next</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">);</span> +</pre></div> +</div> +<p>A complete example of contents stream parser use is given below (example 2). +But before we get there, we need to introduce <code class="docutils literal notranslate"><span class="pre">ppcontext</span></code> object. Conceptually, +<code class="docutils literal notranslate"><span class="pre">ppcontext</span></code> is an owner (memory handler) of objects created on demand (beyond the <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code>). +So far used only with contents stream parser, which might produce quite some data that we want +to release just after used. To create a new context:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pcontext</span> <span class="o">*</span> <span class="n">ppcontext_new</span> <span class="p">(</span><span class="n">void</span><span class="p">);</span> +</pre></div> +</div> +<p>It initializes a new context and its internal memory heap, taking about 64kB on start. After that, +the context is ready to produce objects (contents parsing functions below). Once objects produced +from a given context are no longer needed:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">ppcontext_done</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">);</span> +</pre></div> +</div> +<p>It restores the context to its initial state, as after <code class="docutils literal notranslate"><span class="pre">ppcontext_new()</span></code>. It means that the context +is ready to produce another bunch of beings (in the example below, all objects from the next page contents). +Once the context is not needed anymore:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">ppcontext_free</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">);</span> +</pre></div> +</div> +<p>Now, contents stream parser functions take the context as an argument. Iterator form of contents stream parser +that allows to process the contents operator by operator:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppcontents_first_op</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">psize</span><span class="p">,</span> <span class="n">ppname</span> <span class="o">*</span><span class="n">pname</span><span class="p">);</span> +<span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppcontents_next_op</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">psize</span><span class="p">,</span> <span class="n">ppname</span> <span class="o">*</span><span class="n">pname</span><span class="p">);</span> +</pre></div> +</div> +<p>Returned <code class="docutils literal notranslate"><span class="pre">ppobj</span> <span class="pre">*</span></code> is a pointer to operands list. <code class="docutils literal notranslate"><span class="pre">*psize</span></code> is the number of operands on stack. +The operator itself is stored as <code class="docutils literal notranslate"><span class="pre">*pname</span></code>.</p> +<p>To parse the entire contents stream at once with no stop at every operator:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppcontents_parse</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">psize</span><span class="p">);</span> +</pre></div> +</div> +<p>Returns probably quite long list of all parsed objects (operands and operatos) in one piece. +The number of objects is stored to <code class="docutils literal notranslate"><span class="pre">*psize</span></code>.</p> +<p>[Contents may contain so called inline images, that breaks a simple scheme of operands / operator syntax:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">BI</span> <span class="o"><</span><span class="n">keyval</span> <span class="n">pairs</span><span class="o">></span> <span class="n">ID</span> <span class="o"><</span><span class="n">binary</span> <span class="n">image</span> <span class="n">data</span><span class="o">></span> <span class="n">EI</span> +</pre></div> +</div> +<p>Contents parser treats this genuine triplet as a single piece, producing two operands (dict and string) +followed by <code class="docutils literal notranslate"><span class="pre">EI</span></code> operator name.]</p> +</div> +<div class="section" id="boxes"> +<h2>Boxes<a class="headerlink" href="#boxes" title="Permalink to this headline">¶</a></h2> +<p>Boxes (rectangles) in PDF are roughly 4-number arrays, but with a special intent. +<code class="docutils literal notranslate"><span class="pre">pplib</span></code> provides a basic interface for these special arrays:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span> + <span class="n">ppnum</span> <span class="n">lx</span><span class="p">,</span> <span class="n">ly</span><span class="p">,</span> <span class="n">rx</span><span class="p">,</span> <span class="n">ry</span><span class="p">;</span> +<span class="p">}</span> <span class="n">pprect</span><span class="p">;</span> +</pre></div> +</div> +<p>This type is used only by helper functions - PDF parser is not aware of the rectangle type. +To convert <code class="docutils literal notranslate"><span class="pre">pparray</span></code> to <code class="docutils literal notranslate"><span class="pre">pprect</span></code>:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pprect</span> <span class="o">*</span> <span class="n">pparray_to_rect</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">pprect</span> <span class="o">*</span><span class="n">rect</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">rect</span> <span class="ow">or</span> <span class="n">NULL</span> +</pre></div> +</div> +<p>In example:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pprect</span> <span class="n">rect</span><span class="p">;</span> +<span class="k">if</span> <span class="p">(</span><span class="n">pparray_to_rect</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="o">&</span><span class="n">rect</span><span class="p">)</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">)</span> + <span class="p">;</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">rect</span> +</pre></div> +</div> +<p>To get some image bounding box:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pprect</span> <span class="o">*</span> <span class="n">ppdict_get_rect</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">pprect</span> <span class="o">*</span><span class="n">rect</span><span class="p">);</span> +<span class="o">//</span> <span class="n">eg</span><span class="o">.</span> <span class="n">ppdict_get_rect</span><span class="p">(</span><span class="n">imagedict</span><span class="p">,</span> <span class="s2">"BBox"</span><span class="p">,</span> <span class="o">&</span><span class="n">rect</span><span class="p">)</span> +</pre></div> +</div> +<p>To get some page box:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pprect</span> <span class="o">*</span> <span class="n">ppdict_get_box</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">pprect</span> <span class="o">*</span><span class="n">rect</span><span class="p">);</span> +<span class="o">//</span> <span class="n">eg</span><span class="o">.</span> <span class="n">ppdict_get_box</span><span class="p">(</span><span class="n">pagedict</span><span class="p">,</span> <span class="s2">"MediaBox"</span><span class="p">,</span> <span class="o">&</span><span class="n">rect</span><span class="p">)</span> +</pre></div> +</div> +<p>The later not only checks the pagedict, but also goes through parent page nodes.</p> +</div> +<div class="section" id="transforms"> +<h2>Transforms<a class="headerlink" href="#transforms" title="Permalink to this headline">¶</a></h2> +<p>Transformations are given as 6-number arrays, but with a special intent. +<code class="docutils literal notranslate"><span class="pre">pplib</span></code> provides a basic interface for these special arrays:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span> + <span class="n">ppnum</span> <span class="n">xx</span><span class="p">,</span> <span class="n">xy</span><span class="p">,</span> <span class="n">yx</span><span class="p">,</span> <span class="n">yy</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">;</span> +<span class="p">}</span> <span class="n">ppmatrix</span><span class="p">;</span> +</pre></div> +</div> +<p>This type is used only by helper functions - PDF parser is not aware of the matrix type. +To convert <code class="docutils literal notranslate"><span class="pre">pparray</span></code> to <code class="docutils literal notranslate"><span class="pre">ppmatrix</span></code>:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppmatrix</span> <span class="o">*</span> <span class="n">pparray_to_matrix</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">ppmatrix</span> <span class="o">*</span><span class="n">matrix</span><span class="p">);</span> +</pre></div> +</div> +<p>In example:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppmatrix</span> <span class="n">matrix</span><span class="p">;</span> +<span class="k">if</span> <span class="p">(</span><span class="n">pparray_to_matrix</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="o">&</span><span class="n">matrix</span><span class="p">)</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">)</span> + <span class="p">;</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">matrix</span> +</pre></div> +</div> +<p>To get the matrix from dict:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppmatrix</span> <span class="o">*</span> <span class="n">ppdict_get_matrix</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppmatrix</span> <span class="o">*</span><span class="n">matrix</span><span class="p">);</span> +<span class="o">//</span> <span class="n">eg</span><span class="o">.</span> <span class="n">ppdict_get_matrix</span><span class="p">(</span><span class="n">imagedict</span><span class="p">,</span> <span class="s2">"Matrix"</span><span class="p">,</span> <span class="o">&</span><span class="n">matrix</span><span class="p">)</span> +</pre></div> +</div> +</div> +<div class="section" id="errors-handling"> +<h2>Errors handling<a class="headerlink" href="#errors-handling" title="Permalink to this headline">¶</a></h2> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> is not verbose, but might happen that it needs to log some error message, eg. when parsing +of some PDF boject fails due to invalid offsets. By default, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> prints the message to stdout, eg.:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">invalid</span> <span class="mi">123</span> <span class="mi">0</span> <span class="n">R</span> <span class="nb">object</span> <span class="n">at</span> <span class="n">offset</span> <span class="mi">123123</span> +</pre></div> +</div> +<p>To replace the default logger, you can provide your own:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">pplog_callback</span> <span class="p">(</span><span class="n">pplogger_callback</span> <span class="n">logger</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">alien</span><span class="p">);</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">pplogger_callback</span></code> is a function:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">your_callback</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">message</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">alien</span><span class="p">);</span> +</pre></div> +</div> +<p>In example, to redirect messages to stderr you may define a function:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">your_callback</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">message</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">alien</span><span class="p">)</span> +<span class="p">{</span> + <span class="n">fprintf</span><span class="p">((</span><span class="n">FILE</span> <span class="o">*</span><span class="p">)</span><span class="n">alien</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">ooops: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">message</span><span class="p">);</span> +<span class="p">}</span> +</pre></div> +</div> +<p>Then set the callback somewhere before loading documents:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pplog_callback</span><span class="p">(</span><span class="n">your_callback</span><span class="p">,</span> <span class="n">stderr</span><span class="p">);</span> +</pre></div> +</div> +<p>(example 2 uses that).</p> +<p>To set the default log messages prefix, eg. <code class="docutils literal notranslate"><span class="pre">pplib:</span></code>, use:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">pplog_prefix</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">prefix</span><span class="p">)</span> +</pre></div> +</div> +<p>Default is empty. The function succeeds if provided prefix is reasonably short (less then 32 bytes).</p> +</div> +</div> + + + </div> + </div> + </div> + <div class="clearer"></div> + </div> + <div class="related" role="navigation" aria-label="related navigation"> + <h3>Navigation</h3> + <ul> + <li class="right" style="margin-right: 10px"> + <a href="genindex.html" title="General Index" + >index</a></li> + <li class="right" > + <a href="ppcode.html" title="Examples" + >next</a> |</li> + <li class="right" > + <a href="ppapi-2.x.html" title="pplib 2.x" + >previous</a> |</li> + <li class="nav-item nav-item-0"><a href="pplib.html">pplib 0.1 documentation</a> »</li> + </ul> + </div> + <div class="footer" role="contentinfo"> + © Copyright 2019, p.jackowski@gust.org.pl. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5. + </div> + </body> +</html>
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppapi-2.x.html b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppapi-2.x.html new file mode 100644 index 00000000000..cac0fcec997 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppapi-2.x.html @@ -0,0 +1,1031 @@ + + +<!doctype html> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>pplib 2.x — pplib 0.1 documentation</title> + <link rel="stylesheet" href="_static/bizstyle.css" type="text/css" /> + <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> + + <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> + <script type="text/javascript" src="_static/jquery.js"></script> + <script type="text/javascript" src="_static/underscore.js"></script> + <script type="text/javascript" src="_static/doctools.js"></script> + <script type="text/javascript" src="_static/language_data.js"></script> + <script type="text/javascript" src="_static/bizstyle.js"></script> + <link rel="index" title="Index" href="genindex.html" /> + <link rel="search" title="Search" href="search.html" /> + <link rel="next" title="pplib 1.x" href="ppapi-1.x.html" /> + <link rel="prev" title="1.x vs 2.x" href="ppnew.html" /> + <meta name="viewport" content="width=device-width,initial-scale=1.0"> + <!--[if lt IE 9]> + <script type="text/javascript" src="_static/css3-mediaqueries.js"></script> + <![endif]--> + </head><body> + <div class="related" role="navigation" aria-label="related navigation"> + <h3>Navigation</h3> + <ul> + <li class="right" style="margin-right: 10px"> + <a href="genindex.html" title="General Index" + accesskey="I">index</a></li> + <li class="right" > + <a href="ppapi-1.x.html" title="pplib 1.x" + accesskey="N">next</a> |</li> + <li class="right" > + <a href="ppnew.html" title="1.x vs 2.x" + accesskey="P">previous</a> |</li> + <li class="nav-item nav-item-0"><a href="pplib.html">pplib 0.1 documentation</a> »</li> + </ul> + </div> + <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> + <div class="sphinxsidebarwrapper"> + <h3><a href="pplib.html">Table of Contents</a></h3> + <ul> +<li><a class="reference internal" href="#"><code class="docutils literal notranslate"><span class="pre">pplib</span></code> 2.x</a></li> +<li><a class="reference internal" href="#c-api">C-API</a><ul> +<li><a class="reference internal" href="#types">Types</a></li> +<li><a class="reference internal" href="#object">Object</a></li> +<li><a class="reference internal" href="#names">Names</a></li> +<li><a class="reference internal" href="#string">String</a></li> +<li><a class="reference internal" href="#array">Array</a></li> +<li><a class="reference internal" href="#dict">Dict</a></li> +<li><a class="reference internal" href="#stream">Stream</a></li> +<li><a class="reference internal" href="#filters">Filters</a></li> +<li><a class="reference internal" href="#ref">Ref</a></li> +<li><a class="reference internal" href="#xref">XRef</a></li> +<li><a class="reference internal" href="#pdf">PDF</a></li> +<li><a class="reference internal" href="#encryption">Encryption</a></li> +<li><a class="reference internal" href="#pages">Pages</a></li> +<li><a class="reference internal" href="#contents">Contents</a></li> +<li><a class="reference internal" href="#boxes">Boxes</a></li> +<li><a class="reference internal" href="#transforms">Transforms</a></li> +<li><a class="reference internal" href="#errors-handling">Errors handling</a></li> +</ul> +</li> +</ul> + + <h4>Previous topic</h4> + <p class="topless"><a href="ppnew.html" + title="previous chapter">1.x vs 2.x</a></p> + <h4>Next topic</h4> + <p class="topless"><a href="ppapi-1.x.html" + title="next chapter"><code class="docutils literal notranslate"><span class="pre">pplib</span></code> 1.x</a></p> + <div role="note" aria-label="source link"> + <h3>This Page</h3> + <ul class="this-page-menu"> + <li><a href="_sources/ppapi-2.x.rst.txt" + rel="nofollow">Show Source</a></li> + </ul> + </div> +<div id="searchbox" style="display: none" role="search"> + <h3>Quick search</h3> + <div class="searchformwrapper"> + <form class="search" action="search.html" method="get"> + <input type="text" name="q" /> + <input type="submit" value="Go" /> + <input type="hidden" name="check_keywords" value="yes" /> + <input type="hidden" name="area" value="default" /> + </form> + </div> +</div> +<script type="text/javascript">$('#searchbox').show(0);</script> + </div> + </div> + + <div class="document"> + <div class="documentwrapper"> + <div class="bodywrapper"> + <div class="body" role="main"> + + <div class="section" id="pplib-2-x"> +<h1><code class="docutils literal notranslate"><span class="pre">pplib</span></code> 2.x<a class="headerlink" href="#pplib-2-x" title="Permalink to this headline">¶</a></h1> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> is a library for raw PDF access. It parses PDF documents and provides an interface to access document structures in C.</p> +</div> +<div class="section" id="c-api"> +<h1>C-API<a class="headerlink" href="#c-api" title="Permalink to this headline">¶</a></h1> +<div class="section" id="types"> +<h2>Types<a class="headerlink" href="#types" title="Permalink to this headline">¶</a></h2> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> defines several C-types to represent PDF types:</p> +<ul class="simple"> +<li><code class="docutils literal notranslate"><span class="pre">ppbyte</span></code> - char</li> +<li><code class="docutils literal notranslate"><span class="pre">ppint</span></code> - signed integer (<code class="docutils literal notranslate"><span class="pre">int64_t</span></code>)</li> +<li><code class="docutils literal notranslate"><span class="pre">ppnum</span></code> - real number (double)</li> +<li><code class="docutils literal notranslate"><span class="pre">ppname</span></code> - PDF name</li> +<li><code class="docutils literal notranslate"><span class="pre">ppstring</span></code> - PDF string</li> +<li><code class="docutils literal notranslate"><span class="pre">pparray</span></code> - PDF array</li> +<li><code class="docutils literal notranslate"><span class="pre">ppdict</span></code> - PDF dict</li> +<li><code class="docutils literal notranslate"><span class="pre">ppstream</span></code> - PDF stream</li> +<li><code class="docutils literal notranslate"><span class="pre">ppref</span></code> - PDF indirect reference</li> +<li><code class="docutils literal notranslate"><span class="pre">ppobj</span></code> - a container of all above</li> +</ul> +<p>Among <code class="docutils literal notranslate"><span class="pre">ppint</span></code> and <code class="docutils literal notranslate"><span class="pre">ppnum</span></code>, we also use <code class="docutils literal notranslate"><span class="pre">ppuint</span></code> - unsigned integer (machine word, alias to <code class="docutils literal notranslate"><span class="pre">size_t</span></code>).</p> +<p>Other API types:</p> +<ul class="simple"> +<li><code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> - PDF document</li> +<li><code class="docutils literal notranslate"><span class="pre">ppxref</span></code> - cross-references table</li> +<li><code class="docutils literal notranslate"><span class="pre">ppcontext</span></code> - … later</li> +<li><code class="docutils literal notranslate"><span class="pre">pprect</span></code> - rectangle</li> +<li><code class="docutils literal notranslate"><span class="pre">ppmatrix</span></code> - matrix</li> +</ul> +<p>Integer and number are as simple types. Names and strings used to be aliases to <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">*</span></code> +in <code class="docutils literal notranslate"><span class="pre">pplib</span> <span class="pre">1.x</span></code>, now they are structures; all related API functions operate on pointers. +Other types (array, dict, stream, reference, object container, xref, doc) are C-structures, +and you operate it their pointers. So when you declare a simple type variable you say:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppuint</span> <span class="n">u</span><span class="p">;</span> +<span class="n">ppnum</span> <span class="n">n</span><span class="p">;</span> +<span class="o">...</span> +</pre></div> +</div> +<p>And when you declare a compound type you operate on pointers:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span><span class="n">obj</span><span class="p">;</span> +<span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span> +<span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">;</span> +<span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">;</span> +<span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">;</span> +<span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">;</span> +<span class="n">ppref</span> <span class="o">*</span><span class="n">ref</span><span class="p">;</span> +<span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">;</span> +</pre></div> +</div> +<p>Most of those C-types are defined in library header <code class="docutils literal notranslate"><span class="pre">ppapi.h</span></code> (complete types). Some others are incomplete +(eg. you can’t say <code class="docutils literal notranslate"><span class="pre">sizeof(ppdoc)</span></code> or <code class="docutils literal notranslate"><span class="pre">sizeof(ppxref)</span></code>). This is to avoid unnecesary dependencies in +the header. The library itself uses <code class="docutils literal notranslate"><span class="pre">pplib.h</span></code> header but for auxilary applications including a standalone +<code class="docutils literal notranslate"><span class="pre">ppapi.h</span></code> header should be enough.</p> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> was designed having <strong>read-only</strong> PDF access in mind. Even if some structure is completelly exposed, +so that you can directly access its members, you should treat them as read-only. I don’t make them <code class="docutils literal notranslate"><span class="pre">const</span></code> because +then all variable declarations would need to be <code class="docutils literal notranslate"><span class="pre">const</span></code>, which is annoying, and I’d need some trickery in the library +internals to unconst. Besides, nothing is really const for C type casts.</p> +</div> +<div class="section" id="object"> +<h2>Object<a class="headerlink" href="#object" title="Permalink to this headline">¶</a></h2> +<p>A common container for all elementary PDF object types is <code class="docutils literal notranslate"><span class="pre">ppobj</span></code> structure. <code class="docutils literal notranslate"><span class="pre">ppobj</span></code> has a type identifier +(integer) and union of values:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">struct</span> <span class="n">ppobj</span> <span class="p">{</span> + <span class="n">ppobjtp</span> <span class="nb">type</span><span class="p">;</span> + <span class="n">union</span> <span class="p">{</span> + <span class="n">ppint</span> <span class="n">integer</span><span class="p">;</span> + <span class="n">ppnum</span> <span class="n">number</span><span class="p">;</span> + <span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span> + <span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">;</span> + <span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">;</span> + <span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">;</span> + <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">;</span> + <span class="n">ppref</span> <span class="o">*</span><span class="n">ref</span><span class="p">;</span> + <span class="n">void</span> <span class="o">*</span><span class="nb">any</span><span class="p">;</span> + <span class="p">};</span> +<span class="p">};</span> +</pre></div> +</div> +<p>Object type is one of constants (enum):</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PPNONE</span> +<span class="n">PPNULL</span> +<span class="n">PPBOOL</span> +<span class="n">PPINT</span> +<span class="n">PPNUM</span> +<span class="n">PPNAME</span> +<span class="n">PPSTRING</span> +<span class="n">PPARRAY</span> +<span class="n">PPDICT</span> +<span class="n">PPSTREAM</span> +<span class="n">PPREF</span> +</pre></div> +</div> +<p>The type determines the structure member you’re allowed to access:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span><span class="n">obj</span><span class="p">;</span> +<span class="o">...</span> +<span class="n">switch</span> <span class="p">(</span><span class="n">obj</span><span class="o">-></span><span class="nb">type</span><span class="p">)</span> +<span class="p">{</span> + <span class="n">case</span> <span class="n">PPNONE</span><span class="p">:</span> <span class="o">//</span> <span class="n">shouldn</span><span class="s1">'t actually happen, indicates some failure</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPNULL</span><span class="p">:</span> <span class="o">//</span> <span class="n">valid</span> <span class="n">PDF</span> <span class="n">null</span> <span class="nb">object</span><span class="p">,</span> <span class="n">no</span> <span class="n">value</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPBOOL</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">integer</span> <span class="p">(</span><span class="n">ppint</span><span class="p">),</span> <span class="n">value</span> <span class="mi">0</span> <span class="ow">or</span> <span class="mi">1</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPINT</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">integer</span> <span class="p">(</span><span class="n">ppint</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPNUM</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">number</span> <span class="p">(</span><span class="n">ppnum</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPNAME</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">name</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPSTRING</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">string</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPARRAY</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">array</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPDICT</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="nb">dict</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPSTREAM</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">stream</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPREF</span><span class="p">:</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">obj</span><span class="o">-></span><span class="n">ref</span> <span class="p">(</span><span class="n">ppref</span> <span class="o">*</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> +<span class="p">}</span> +</pre></div> +</div> +<p>More often then not you know exactly what type of object value is expected, in which case +you may use one of the following macros:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">//</span> <span class="n">returns</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPNULL</span> +<span class="nb">int</span> <span class="n">ppobj_get_null</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> \ + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPBOOL</span><span class="p">,</span> <span class="n">sets</span> <span class="nb">int</span> <span class="n">v</span> <span class="n">to</span> <span class="mi">0</span> <span class="ow">or</span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">returns</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span> <span class="n">otherwise</span> +<span class="nb">int</span> <span class="n">ppobj_get_bool</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPINT</span><span class="p">,</span> <span class="n">sets</span> <span class="n">ppint</span> <span class="n">v</span> <span class="ow">and</span> <span class="n">returns</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span> <span class="n">otherwise</span> +<span class="nb">int</span> <span class="n">ppobj_get_int</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPINT</span> <span class="ow">and</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">sets</span> <span class="n">ppuint</span> <span class="n">v</span> <span class="ow">and</span> <span class="n">returns</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span> <span class="n">otherwise</span> +<span class="nb">int</span> <span class="n">ppobj_get_uint</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPNUM</span> <span class="ow">or</span> <span class="n">PPINT</span><span class="p">,</span> <span class="n">sets</span> <span class="n">ppnum</span> <span class="n">v</span> <span class="ow">and</span> <span class="n">returns</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span> <span class="n">otherwise</span> +<span class="nb">int</span> <span class="n">ppobj_get_num</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPNAME</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">name</span><span class="p">,</span> <span class="n">NULL</span> <span class="n">otherwise</span> +<span class="n">ppname</span> <span class="o">*</span> <span class="n">ppobj_get_name</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPSTRING</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">string</span><span class="p">,</span> <span class="n">NULL</span> <span class="n">otherwise</span> +<span class="n">ppstring</span> <span class="o">*</span> <span class="n">ppobj_get_string</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPARRAY</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">array</span><span class="p">,</span> <span class="n">NULL</span> <span class="n">otherwise</span> +<span class="n">pparray</span> <span class="o">*</span> <span class="n">ppobj_get_array</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPDICT</span> <span class="n">returns</span> <span class="n">the</span> <span class="nb">dict</span><span class="p">,</span> <span class="n">NULL</span> <span class="n">otherwise</span> +<span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppobj_get_dict</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPSTREAM</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">stream</span><span class="p">,</span> <span class="n">NULL</span> <span class="n">otherwise</span> +<span class="n">ppstream</span> <span class="o">*</span> <span class="n">ppobj_get_stream</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> + +<span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPREF</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">reference</span><span class="p">,</span> <span class="n">NULL</span> <span class="n">otherwise</span> +<span class="n">ppref</span> <span class="o">*</span> <span class="n">ppobj_get_ref</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> +</pre></div> +</div> +<p>Note the coercion from integer to real number, but not reverse. In practise, whenever you expect a real number, +you should also handle integer (eg. ‘1’ used instead of ‘1.0’ is pretty common in PDF).</p> +<p>It is a common case that the object is given as an indirect reference, but what you actually +want is not the reference, but the object referred by it. Here is a helper for it:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">//</span> <span class="k">if</span> <span class="n">o</span><span class="o">-></span><span class="nb">type</span> <span class="ow">is</span> <span class="n">PPREF</span><span class="p">,</span> <span class="n">returns</span> <span class="n">what</span> <span class="n">the</span> <span class="n">reference</span> <span class="n">points</span><span class="p">,</span> <span class="n">otherwise</span> <span class="n">returns</span> <span class="n">o</span> +<span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppobj_rget_obj</span><span class="p">(</span><span class="n">o</span><span class="p">)</span> +</pre></div> +</div> +<p>Also every <code class="docutils literal notranslate"><span class="pre">ppobj_get_*</span></code> macro has <code class="docutils literal notranslate"><span class="pre">ppobj_rget_*</span></code> counterpart that makes a check +for the expected type, but if the object is PPREF, it jumps to the target object. +So for example <code class="docutils literal notranslate"><span class="pre">ppobj_rget_dict(obj)</span></code> will return dict if <code class="docutils literal notranslate"><span class="pre">obj</span></code> is of type PPDICT +or if it is of type PPREF and <code class="docutils literal notranslate"><span class="pre">obj->ref</span></code> hosts an object of type PPDICT.</p> +</div> +<div class="section" id="names"> +<h2>Names<a class="headerlink" href="#names" title="Permalink to this headline">¶</a></h2> +<p>PDF names are represented as <code class="docutils literal notranslate"><span class="pre">ppname</span></code> pointer (<code class="docutils literal notranslate"><span class="pre">ppname</span></code> used to be an alias to <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">*</span></code>, now it is a structure). +To access the name data:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppname_data</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="o">//</span> <span class="n">name</span><span class="o">-></span><span class="n">data</span><span class="p">,</span> <span class="nb">bytes</span> <span class="n">array</span> +</pre></div> +</div> +<p>For convenient use in C, names are <code class="docutils literal notranslate"><span class="pre">'\0'</span></code> terminated. But to get the length of name better always use +<code class="docutils literal notranslate"><span class="pre">ppname_size()</span></code> macro. <code class="docutils literal notranslate"><span class="pre">ppname</span></code> object knows its size, don’t use <code class="docutils literal notranslate"><span class="pre">strlen()</span></code>:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">size_t</span> <span class="n">ppname_size</span><span class="p">(</span><span class="n">ppname</span> <span class="n">name</span><span class="p">);</span> <span class="o">//</span> <span class="n">name</span><span class="o">-></span><span class="n">size</span><span class="p">,</span> <span class="n">the</span> <span class="n">length</span> <span class="n">of</span> <span class="n">name</span> <span class="ow">in</span> <span class="nb">bytes</span> +</pre></div> +</div> +<p>In current implementation names are not hashed anyhow, so name-to-name comparison is not smarter than <code class="docutils literal notranslate"><span class="pre">memcmp()</span></code>. +Use macros:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">ppname_is</span><span class="p">(</span><span class="n">ppname</span> <span class="n">name</span><span class="p">,</span> <span class="s2">"literal"</span><span class="p">);</span> <span class="o">//</span> <span class="n">to</span> <span class="n">compare</span> <span class="n">ppname</span> <span class="k">with</span> <span class="n">C</span><span class="o">-</span><span class="n">literal</span> <span class="n">string</span> +<span class="nb">int</span> <span class="n">ppname_eq</span><span class="p">(</span><span class="n">ppname</span> <span class="n">name</span><span class="p">,</span> <span class="n">ppname</span> <span class="n">other</span><span class="p">);</span> <span class="o">//</span> <span class="n">to</span> <span class="n">compare</span> <span class="n">ppname</span> <span class="k">with</span> <span class="n">a</span> <span class="n">different</span> <span class="n">name</span> +</pre></div> +</div> +<p>If you use <code class="docutils literal notranslate"><span class="pre">pplib</span></code> to parse contents streams, you may need to distinguish names from operators +(more precisely executable names). Names in PDF are preceeded by ‘/’, executable names aren’t. In both +cases PDF parser will produce <code class="docutils literal notranslate"><span class="pre">ppname</span></code> but the result can be distingushed with:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">ppname_exec</span><span class="p">(</span><span class="n">ppname</span> <span class="n">name</span><span class="p">);</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">non</span><span class="o">-</span><span class="n">zero</span> <span class="k">if</span> <span class="n">the</span> <span class="n">name</span> <span class="ow">is</span> <span class="n">executable</span> +</pre></div> +</div> +<p>Names are kept in their raw form, with possible PDF specific escapes (in text below we call it <strong>encoded</strong> form). +Leading ‘/’ is omitted. One may need a decoded name, with no PDF escapes. +A pair of functions provides a simple interface to switch between those two forms:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">//</span> <span class="n">these</span> <span class="n">helpers</span> <span class="n">rely</span> <span class="n">on</span> <span class="n">name</span><span class="o">-></span><span class="n">alterego</span> <span class="n">member</span> +<span class="n">ppname</span> <span class="o">*</span> <span class="n">ppname_decoded</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">decoded</span> <span class="p">(</span><span class="n">unescaped</span><span class="p">)</span> <span class="n">form</span> <span class="n">of</span> <span class="n">the</span> <span class="n">name</span> +<span class="n">ppname</span> <span class="o">*</span> <span class="n">ppname_encoded</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">encoded</span> <span class="p">(</span><span class="n">escaped</span><span class="p">)</span> <span class="n">form</span> <span class="n">of</span> <span class="n">the</span> <span class="n">name</span> +<span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppname_decoded_data</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppname_encoded_data</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +</pre></div> +</div> +<p>In pretty most cases a PDF name contains only letters (no special characters, no escapes), so decoded and encoded forms are identical. +In that case both functions simply return the argument. It is ok to call <code class="docutils literal notranslate"><span class="pre">ppname_decoded()</span></code> on already decoded form +and <code class="docutils literal notranslate"><span class="pre">ppname_encoded()</span></code> on already encoded form. Both forms are produced by PDF objects parser, so accessing <code class="docutils literal notranslate"><span class="pre">ppname</span></code> alter ego +in whatever direction needs no extra decoding or allocation costs (the cost is paid by parser).</p> +</div> +<div class="section" id="string"> +<h2>String<a class="headerlink" href="#string" title="Permalink to this headline">¶</a></h2> +<p>PDF strings have the same internal construction as names, so most of names description above applies to strings as well. +<code class="docutils literal notranslate"><span class="pre">ppstring</span></code> is a structure (used to be an alias to <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">*</span></code>). <code class="docutils literal notranslate"><span class="pre">string->data</span></code> is <code class="docutils literal notranslate"><span class="pre">\0</span></code>-terminated c-array of <code class="docutils literal notranslate"><span class="pre">ppbytes</span></code>. +To get the data:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppstring_data</span><span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> <span class="o">//</span> <span class="n">string</span><span class="o">-></span><span class="n">data</span><span class="p">,</span> <span class="n">macro</span> +</pre></div> +</div> +<p>To get the size of the string:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">size_t</span> <span class="n">ppstring_size</span><span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">length</span> <span class="n">of</span> <span class="n">the</span> <span class="n">string</span> <span class="ow">in</span> <span class="nb">bytes</span> +</pre></div> +</div> +<p>Strings are provided in their raw form, preserving PDF specific escapes, but with no +<code class="docutils literal notranslate"><span class="pre">()</span></code> or <code class="docutils literal notranslate"><span class="pre"><></span></code> delims. To distinguish plain strings from hex strings:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">ppstring_hex</span><span class="p">(</span><span class="n">ppstring</span> <span class="n">string</span><span class="p">);</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">non</span> <span class="n">zero</span> <span class="k">if</span> <span class="nb">hex</span> <span class="n">string</span> +</pre></div> +</div> +<p>Or if you prefer:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>switch (ppstring_type(string)) +{ + case PPSTRING_PLAIN: // literal string, surrounded by ``(`` and ``)`` in PDF + break; + case PPSTRING_BASE16: // hex string, surrounded by ``<`` and ``>`` in PDF + break; + case PPSTRING_BASE85: // base85 string surrounded by ``<~`` and ``~>`` in PDF + break; +} +</pre></div> +</div> +<p>The last is actually Postscript specific, not used in PDF, but I think it might appear in contents streams… +No matter how the string is given in PDF (plain or hex), here are two functions to +switch between encoded and decoded strings forms:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstring</span> <span class="o">*</span> <span class="n">ppstring_decoded</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">decoded</span> <span class="n">string</span> <span class="n">possibly</span> <span class="k">with</span> <span class="n">PDF</span> <span class="n">escapes</span> +<span class="n">ppstring</span> <span class="o">*</span> <span class="n">ppstring_encoded</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">encoded</span> <span class="n">string</span> <span class="k">with</span> <span class="n">no</span> <span class="n">PDF</span> <span class="n">escapes</span> +<span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppstring_decoded_data</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> +<span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppstring_encoded_data</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> +</pre></div> +</div> +<p>For hex strings, encoded form contains hex digits, while decoded form contains arbitrary bytes (the result of hex decoding). +Plain strings usually contains printable ASCII characters, but they might contain any binary data. +As with names, objects parser produces both forms. The raw form with PDF escapes (or raw hex form) the main one. +Eg. when you access <code class="docutils literal notranslate"><span class="pre">obj->string</span></code> you always get the encoded form. At any moment you can switch to its alter ego.</p> +<p>No matter if the string is plain or hex, if its first two bytes (decoded) are UTF16 BOM, the string is unicode. +<code class="docutils literal notranslate"><span class="pre">ppstring</span></code> object <em>knows</em> it is unicode or not:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">switch</span> <span class="p">(</span><span class="n">ppstring_utf</span><span class="p">(</span><span class="n">string</span><span class="p">))</span> +<span class="p">{</span> + <span class="n">case</span> <span class="n">PPSTRING_UTF16LE</span><span class="p">:</span> <span class="o">//</span> <span class="n">unicode</span> <span class="n">string</span><span class="p">,</span> <span class="n">utf16le</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPSTRING_UTF16BE</span><span class="p">:</span> <span class="o">//</span> <span class="n">unicode</span> <span class="n">string</span><span class="p">,</span> <span class="n">utf16be</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">default</span><span class="p">:</span> <span class="o">//</span> <span class="n">no</span> <span class="n">unicode</span> +<span class="p">}</span> +</pre></div> +</div> +<p>Or simply:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">ppstring_utf</span><span class="p">(</span><span class="n">string</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> + <span class="o">//</span> <span class="n">handle</span> <span class="n">unicode</span> <span class="n">string</span> +<span class="p">}</span> +</pre></div> +</div> +<p>If the string is unicode, BOM remains the part of the string – <code class="docutils literal notranslate"><span class="pre">pplib</span></code> parser does not strip it. +Unicode or not, encoded or decoded, strings are always C-arrays of bytes and <code class="docutils literal notranslate"><span class="pre">ppstring_size()</span></code> +always returns the size in bytes.</p> +</div> +<div class="section" id="array"> +<h2>Array<a class="headerlink" href="#array" title="Permalink to this headline">¶</a></h2> +<p>PDF arrays are represented as <code class="docutils literal notranslate"><span class="pre">pparray</span></code> type, which is C-array of <code class="docutils literal notranslate"><span class="pre">ppobj</span></code> structures. +To get the size:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">size_t</span> <span class="n">pparray_size</span><span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">number</span> <span class="n">of</span> <span class="n">array</span> <span class="n">items</span> +</pre></div> +</div> +<p>To get <code class="docutils literal notranslate"><span class="pre">ppobj</span> <span class="pre">*</span></code> at a given index:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span> <span class="n">pparray_at</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">ppobj</span> <span class="o">*</span> <span class="p">(</span><span class="n">no</span> <span class="n">index</span> <span class="n">check</span><span class="p">)</span> +<span class="n">ppobj</span> <span class="o">*</span> <span class="n">pparray_get</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">ppobj</span> <span class="o">*</span> <span class="ow">or</span> <span class="n">NULL</span> <span class="p">(</span><span class="k">with</span> <span class="n">index</span> <span class="n">check</span><span class="p">)</span> +<span class="n">ppobj</span> <span class="o">*</span> <span class="n">pparray_get_obj</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span> <span class="n">function</span> <span class="n">equiv</span> <span class="n">to</span> <span class="n">pparray_get</span><span class="p">()</span> +</pre></div> +</div> +<p>Iterating over array elements:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">;</span> +<span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +<span class="n">ppobj</span> <span class="o">*</span><span class="n">obj</span><span class="p">;</span> +<span class="k">for</span> <span class="p">(</span><span class="n">size</span> <span class="o">=</span> <span class="n">pparray_size</span><span class="p">(</span><span class="n">array</span><span class="p">),</span> <span class="n">pparray_first</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">index</span><span class="p">,</span> <span class="n">obj</span><span class="p">);</span> <span class="n">index</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="n">pparray_next</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">obj</span><span class="p">))</span> +<span class="p">{</span> + <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">index</span> <span class="ow">and</span> <span class="n">obj</span> +<span class="p">}</span> +</pre></div> +</div> +<p>There is no magic first/next macros, just iteration over pointers. One could also use something like:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="p">(</span><span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">size</span> <span class="o">=</span> <span class="n">array</span><span class="o">-></span><span class="n">size</span><span class="p">;</span> <span class="n">index</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="o">++</span><span class="n">index</span><span class="p">)</span> +<span class="p">{</span> + <span class="n">obj</span> <span class="o">=</span> <span class="n">pparray_at</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">index</span><span class="p">);</span> + <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">index</span> <span class="ow">and</span> <span class="n">obj</span> +<span class="p">}</span> +</pre></div> +</div> +<p>When getting values from array and expecting a result of known type, use one of the following:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">pparray_get_bool</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="nb">int</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">boolean</span> <span class="n">value</span> +<span class="nb">int</span> <span class="n">pparray_get_int</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">ppint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppint</span> <span class="n">value</span> +<span class="nb">int</span> <span class="n">pparray_get_uint</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">ppuint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppuint</span> <span class="n">value</span> +<span class="nb">int</span> <span class="n">pparray_get_num</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">ppnum</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppnum</span> <span class="n">value</span> +<span class="n">ppname</span> <span class="o">*</span> <span class="n">pparray_get_name</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppname</span> <span class="o">*</span> <span class="n">value</span> +<span class="n">ppstring</span> <span class="o">*</span> <span class="n">pparray_get_string</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppstring</span> <span class="o">*</span> <span class="n">value</span> +<span class="n">pparray</span> <span class="o">*</span> <span class="n">pparray_get_array</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">pparray</span> <span class="o">*</span> <span class="n">value</span> +<span class="n">ppdict</span> <span class="o">*</span> <span class="n">pparray_get_dict</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppdict</span> <span class="o">*</span> <span class="n">value</span> +<span class="n">ppref</span> <span class="o">*</span> <span class="n">pparray_get_ref</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span> <span class="n">get</span> <span class="n">ppref</span> <span class="o">*</span> <span class="n">value</span> +</pre></div> +</div> +<p>As with <code class="docutils literal notranslate"><span class="pre">ppobj_get_*</span></code> suite, numeric types getters set the value of a given type and returns 1, if the type matches. +Otherwise sets nothing and returns 0. Other getters return the value if the type matches, or NULL.</p> +<p>Every function from <code class="docutils literal notranslate"><span class="pre">pparray_get_*</span></code> suite have its <code class="docutils literal notranslate"><span class="pre">pparray_rget_*</span></code> counterpart +that dereferences indirect objects (as explained for <code class="docutils literal notranslate"><span class="pre">ppobj_rget_*</span></code> getters). Note that +there is no <code class="docutils literal notranslate"><span class="pre">pparray_get_stream()</span></code> function, as streams in PDF are always indirect +(may only reside in <code class="docutils literal notranslate"><span class="pre">ref->object.stream</span></code>). To get the stream from array use:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream</span> <span class="o">*</span> <span class="n">pparray_rget_stream</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> +</pre></div> +</div> +</div> +<div class="section" id="dict"> +<h2>Dict<a class="headerlink" href="#dict" title="Permalink to this headline">¶</a></h2> +<p>PDF dicts are represented as <code class="docutils literal notranslate"><span class="pre">ppdict</span></code> structure, which is C-array of <code class="docutils literal notranslate"><span class="pre">ppobj</span></code> with parallel +C-array of <code class="docutils literal notranslate"><span class="pre">ppname</span></code> pointers. To get the size of a dict:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">size_t</span> <span class="n">ppdict_size</span><span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">the</span> <span class="n">number</span> <span class="n">of</span> <span class="n">key</span><span class="o">-</span><span class="n">val</span> <span class="n">pairs</span> +</pre></div> +</div> +<p>To get the value at a given index (integer):</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppdict_at</span><span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">no</span> <span class="n">index</span> <span class="n">bounds</span> <span class="n">check</span> +</pre></div> +</div> +<p>To get the name (key) at a given index:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppname</span> <span class="o">*</span> <span class="n">ppdict_key</span><span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">no</span> <span class="n">index</span> <span class="n">bounds</span> <span class="n">check</span> +</pre></div> +</div> +<p>To iterate over dict key-val pairs:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">;</span> +<span class="n">ppname</span> <span class="o">**</span><span class="n">pkey</span><span class="p">;</span> +<span class="n">ppobj</span> <span class="o">*</span><span class="n">obj</span><span class="p">;</span> + +<span class="k">for</span> <span class="p">(</span><span class="n">ppdict_first</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">pkey</span><span class="p">,</span> <span class="n">obj</span><span class="p">);</span> <span class="o">*</span><span class="n">pkey</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">;</span> <span class="n">ppdict_next</span><span class="p">(</span><span class="n">pkey</span><span class="p">,</span> <span class="n">obj</span><span class="p">))</span> +<span class="p">{</span> + <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="o">*</span><span class="n">pkey</span> <span class="ow">and</span> <span class="n">obj</span> +<span class="p">}</span> +</pre></div> +</div> +<p>There is no magic in first/next macros, just iteration through keys and values lists pointers. +For convenient iteration, a list of keys is terminated with NULL, so in the code above <code class="docutils literal notranslate"><span class="pre">*pkey</span> <span class="pre">!=</span> <span class="pre">NULL</span></code> +is used as the loop condition. One may also iterate via indices:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">;</span> +<span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">size</span><span class="p">;</span> +<span class="n">ppname</span> <span class="o">*</span><span class="n">key</span><span class="p">;</span> +<span class="n">ppobj</span> <span class="o">*</span><span class="n">obj</span><span class="p">;</span> +<span class="k">for</span> <span class="p">(</span><span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">size</span> <span class="o">=</span> <span class="n">ppdict_size</span><span class="p">(</span><span class="nb">dict</span><span class="p">);</span> <span class="n">index</span> <span class="o"><</span> <span class="n">size</span><span class="p">;</span> <span class="o">++</span><span class="n">index</span><span class="p">)</span> +<span class="p">{</span> + <span class="n">key</span> <span class="o">=</span> <span class="n">ppdict_key</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">index</span><span class="p">);</span> + <span class="n">obj</span> <span class="o">=</span> <span class="n">ppdict_at</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">index</span><span class="p">);</span> + <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">key</span> <span class="ow">and</span> <span class="n">obj</span> +<span class="p">}</span> +</pre></div> +</div> +<p>To get the object associated with a given name, use one of the following:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppdict_get_obj</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="nb">int</span> <span class="n">ppdict_get_bool</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="nb">int</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> +<span class="nb">int</span> <span class="n">ppdict_get_int</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> +<span class="nb">int</span> <span class="n">ppdict_get_uint</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppuint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> +<span class="nb">int</span> <span class="n">ppdict_get_num</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppnum</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> +<span class="n">ppname</span> <span class="n">ppdict_get_name</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">ppstring</span> <span class="n">ppdict_get_string</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">pparray</span> <span class="o">*</span> <span class="n">ppdict_get_array</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppdict_get_dict</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">ppref</span> <span class="o">*</span> <span class="n">ppdict_get_ref</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +</pre></div> +</div> +<p>Note that all getters accepts <code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*</span></code> as key, so it is ok to say:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdict_rget_dict</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="s2">"Resources"</span><span class="p">);</span> +</pre></div> +</div> +<p>(the most common use I guess). But to use <code class="docutils literal notranslate"><span class="pre">ppname</span></code> object as a key, one have to +use data member:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdic_rget_dict</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">name</span><span class="o">-></span><span class="n">data</span><span class="p">);</span> <span class="o">//</span> <span class="n">ppname</span> <span class="o">*</span><span class="n">name</span> +</pre></div> +</div> +<p>Every <code class="docutils literal notranslate"><span class="pre">ppdict_get_*</span></code> getter has <code class="docutils literal notranslate"><span class="pre">ppdict_rget_*</span></code> counterpart that dereferences +indirect objects if necessary. Note that there is no <code class="docutils literal notranslate"><span class="pre">ppdict_get_stream()</span></code> function, +but there is:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream</span> <span class="o">*</span> <span class="n">ppdict_rget_stream</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +</pre></div> +</div> +<p>So far dicts comes with no names mapping, so by-name dict accessors perform a linear search +through the keys list. PDF dicts are usually small.</p> +</div> +<div class="section" id="stream"> +<h2>Stream<a class="headerlink" href="#stream" title="Permalink to this headline">¶</a></h2> +<p>PDF streams are represented as <code class="docutils literal notranslate"><span class="pre">ppstream</span></code> objects. To get the stream dict:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppstream_dict</span><span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span> +</pre></div> +</div> +<p>To read the stream data:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">uint8_t</span> <span class="o">*</span> <span class="n">ppstream_first</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">size</span><span class="p">,</span> <span class="nb">int</span> <span class="n">decode</span><span class="p">);</span> +<span class="n">uint8_t</span> <span class="o">*</span> <span class="n">ppstream_next</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">size</span><span class="p">);</span> +<span class="n">void</span> <span class="n">ppstream_done</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">);</span> +</pre></div> +</div> +<p>Both <code class="docutils literal notranslate"><span class="pre">first`</span> <span class="pre">and</span> <span class="pre">``next</span></code> functions return a chunk of stream data and sets the <code class="docutils literal notranslate"><span class="pre">size</span></code> of the chunk. +<code class="docutils literal notranslate"><span class="pre">decode</span></code> parameter tell the reader to decompress the stream (1) or return raw (0). A call to <code class="docutils literal notranslate"><span class="pre">ppstream_next()</span></code> +must be preceeded by <code class="docutils literal notranslate"><span class="pre">ppstream_first()</span></code>. Once you’re done with the stream, you have to call <code class="docutils literal notranslate"><span class="pre">ppstream_done()</span></code>, +no matter if the stream has been read to the end or not. The stream data iterator in use:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">uint8_t</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span> +<span class="n">size_t</span> <span class="n">size</span><span class="p">;</span> +<span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">;</span> +<span class="nb">int</span> <span class="n">decode</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="o">//</span> <span class="mi">1</span> <span class="o">-</span> <span class="n">get</span> <span class="n">decompressed</span><span class="p">,</span> <span class="mi">0</span> <span class="o">-</span> <span class="n">get</span> <span class="n">raw</span> + +<span class="k">for</span> <span class="p">(</span><span class="n">data</span> <span class="o">=</span> <span class="n">ppstream_first</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="n">decode</span><span class="p">);</span> <span class="n">data</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">;</span> <span class="n">data</span> <span class="o">=</span> <span class="n">ppstream_next</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">))</span> +<span class="p">{</span> + <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">data</span> <span class="ow">and</span> <span class="n">its</span> <span class="n">size</span> +<span class="p">}</span> +<span class="n">ppstream_done</span><span class="p">(</span><span class="n">stream</span><span class="p">);</span> +</pre></div> +</div> +<p>Every subsequent iterator call invalidates the previous reader output, so you have to utilize the returned chunk +of data just after you ot that. So the following is wrong:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">data1</span> <span class="o">=</span> <span class="n">ppstream_first</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> +<span class="n">data2</span> <span class="o">=</span> <span class="n">ppstream_next</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">);</span> +<span class="n">data3</span> <span class="o">=</span> <span class="n">ppstream_next</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">);</span> +<span class="n">some_output</span><span class="p">(</span><span class="n">data1</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span> +<span class="n">some_output</span><span class="p">(</span><span class="n">data2</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span> +</pre></div> +</div> +<p>The reader calls usually return the same pointer to internal buffer, just filled with a different data. +<code class="docutils literal notranslate"><span class="pre">pplib</span></code> allocates reasonably large buffer and fills that buffer on subsequent calls to the reader.</p> +<p>If the source stream has no compression, using both <code class="docutils literal notranslate"><span class="pre">decode</span> <span class="pre">==</span> <span class="pre">1</span></code> and <code class="docutils literal notranslate"><span class="pre">decode</span> <span class="pre">==</span> <span class="pre">0</span></code> should give the same result. +You can check if the stream is actually compressed with:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream_compressed</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">non</span> <span class="n">zero</span> <span class="k">if</span> <span class="o">/</span><span class="n">Filter</span> <span class="ow">is</span> <span class="n">present</span> +</pre></div> +</div> +<p>It might be necessary to load the entire stream data at once:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">uint8_t</span> <span class="o">*</span> <span class="n">ppstream_all</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">size</span><span class="p">,</span> <span class="nb">int</span> <span class="n">decode</span><span class="p">);</span> +</pre></div> +</div> +<p>If the initial buffer size is insufficient, it grows until the entire stream data is loaded. You must call +<code class="docutils literal notranslate"><span class="pre">ppstream_done(stream)</span></code> after using returned data.</p> +<p><code class="docutils literal notranslate"><span class="pre">ppstream_done()</span></code> doesn’t invalidate the stream object, it just closes its internal reader. +The stream itself remains a valid object (eg. one can read it again if necessary), +but the reader buffer is released. It is actually not freed but kept for future the reuse with that on some other stream, +but you still need to mark it ready for reuse to avoid allocating a separate buffer for every stream you’re going to read.</p> +<p>Stream data readers will return <code class="docutils literal notranslate"><span class="pre">NULL</span></code> if you haven’t close the previous reader process with <code class="docutils literal notranslate"><span class="pre">ppstream_done()</span></code>. All below is wrong:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">data1</span> <span class="o">=</span> <span class="n">ppstream_all</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> +<span class="n">data2</span> <span class="o">=</span> <span class="n">ppstream_all</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="o">//</span> <span class="n">data2</span> <span class="o">==</span> <span class="n">NULL</span> +<span class="o">//</span> <span class="ow">or</span> +<span class="n">data1</span> <span class="o">=</span> <span class="n">ppstream_first</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> +<span class="n">data2</span> <span class="o">=</span> <span class="n">ppstream_first</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="o">//</span> <span class="n">data2</span> <span class="o">==</span> <span class="n">NULL</span> +<span class="o">//</span> <span class="ow">or</span> +<span class="n">data1</span> <span class="o">=</span> <span class="n">ppstream_first</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> +<span class="n">data2</span> <span class="o">=</span> <span class="n">ppstream_all</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="o">//</span> <span class="n">data2</span> <span class="o">==</span> <span class="n">NULL</span> +</pre></div> +</div> +<p>To avoid unnecessary dependencies, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> does not support image filters (<code class="docutils literal notranslate"><span class="pre">/DCT</span></code>, <code class="docutils literal notranslate"><span class="pre">/JPX</span></code>, <code class="docutils literal notranslate"><span class="pre">/JBIG</span></code>, <code class="docutils literal notranslate"><span class="pre">/CCITT</span></code>). +But it is ok to read the stream with <code class="docutils literal notranslate"><span class="pre">decode</span></code> set to 1 on such streams. <code class="docutils literal notranslate"><span class="pre">pplib</span></code> assumes that the image is the +final/target stream form and just returns it as-is. Eg. in the case of JPEG (<code class="docutils literal notranslate"><span class="pre">/DCT</span></code> filtered) image both calls should +give the same results:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream_all</span><span class="p">(</span><span class="n">jpegstream</span><span class="p">,</span> <span class="o">&</span><span class="n">jpegsize</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="o">//</span> <span class="n">don</span><span class="s1">'t decode, return what'</span><span class="n">s</span> <span class="n">there</span> +<span class="n">ppstream_all</span><span class="p">(</span><span class="n">jpegstream</span><span class="p">,</span> <span class="o">&</span><span class="n">jpegsize</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="o">//</span> <span class="n">decode</span> <span class="n">but</span> <span class="n">found</span> <span class="n">image</span> <span class="nb">filter</span><span class="p">,</span> <span class="n">effectively</span> <span class="n">the</span> <span class="n">same</span> +</pre></div> +</div> +<p>A bit more about streams memory. As mentioned, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> allocates buffers for stream readers. After <code class="docutils literal notranslate"><span class="pre">ppstream_done()</span></code>, +the stream no longer <em>owns</em> the buffer space. But the buffer may remain allocated, to be reused with future readers. +<code class="docutils literal notranslate"><span class="pre">pplib</span></code> keeps a pool of several buffers. This means, that when you use stream readers, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> eats +some memory (1MB or so) that is not freed, even if no streams are used. And even if you free all objects. +If you suffer from this, you can optionally use a pair of functions:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">ppstream_init_buffers</span> <span class="p">(</span><span class="n">void</span><span class="p">);</span> +<span class="n">void</span> <span class="n">ppstream_free_buffers</span> <span class="p">(</span><span class="n">void</span><span class="p">);</span> +</pre></div> +</div> +<p>The first initializes buffers pool, unless done so far. Currently <code class="docutils literal notranslate"><span class="pre">pplib</span></code> cares of it before opening every stream reader, +so it is not obligatory. The second frees a pool of buffers. The intended use is to call <code class="docutils literal notranslate"><span class="pre">ppstream_init_buffers()</span></code> once +as kind of library initializer and to call <code class="docutils literal notranslate"><span class="pre">ppstream_free_buffers()</span></code> once, as the library finalizer.</p> +</div> +<div class="section" id="filters"> +<h2>Filters<a class="headerlink" href="#filters" title="Permalink to this headline">¶</a></h2> +<p><code class="docutils literal notranslate"><span class="pre">ppstream</span></code> knows its filter(s) and keps it as <code class="docutils literal notranslate"><span class="pre">stream->filter</span></code>:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">//</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">;</span> +<span class="n">ppstream_filter</span> <span class="o">*</span><span class="n">info</span> <span class="o">=</span> <span class="o">&</span><span class="n">stream</span><span class="o">-></span><span class="nb">filter</span><span class="p">;</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">ppstream_filter</span></code> is the following structure:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span> + <span class="n">ppstreamtp</span> <span class="o">*</span><span class="n">filters</span><span class="p">;</span> <span class="o">//</span> <span class="n">c</span><span class="o">-</span><span class="n">array</span> <span class="n">of</span> <span class="nb">filter</span> <span class="n">identifiers</span> <span class="p">(</span><span class="n">enum</span> <span class="n">integers</span><span class="p">)</span> + <span class="n">ppdict</span> <span class="o">**</span><span class="n">params</span><span class="p">;</span> <span class="o">//</span> <span class="n">c</span><span class="o">-</span><span class="n">array</span> <span class="n">of</span> <span class="n">ppdict</span> <span class="n">pointers</span> + <span class="n">size_t</span> <span class="n">count</span><span class="p">;</span> <span class="o">//</span> <span class="n">number</span> <span class="n">of</span> <span class="n">filters</span><span class="p">,</span> <span class="n">length</span> <span class="n">of</span> <span class="n">the</span> <span class="n">arrays</span> <span class="p">(</span><span class="n">typically</span> <span class="mi">1</span><span class="p">)</span> +<span class="p">}</span> <span class="n">ppstream_filter</span><span class="p">;</span> +</pre></div> +</div> +<p>If <code class="docutils literal notranslate"><span class="pre">count</span> <span class="pre">></span> <span class="pre">0</span></code> then <code class="docutils literal notranslate"><span class="pre">filters</span></code> member is not NULL. Filters array keeps integer constants:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PPSTREAM_BASE16</span> <span class="o">/*</span> <span class="o">/</span><span class="n">ASCIIHexDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_BASE85</span> <span class="o">/*</span> <span class="o">/</span><span class="n">ASCII85Decode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_RUNLENGTH</span> <span class="o">/*</span> <span class="o">/</span><span class="n">RunLengthDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_FLATE</span> <span class="o">/*</span> <span class="o">/</span><span class="n">FlateDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_LZW</span> <span class="o">/*</span> <span class="o">/</span><span class="n">LZWDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_CCITT</span> <span class="o">/*</span> <span class="o">/</span><span class="n">CCITTFaxDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_DCT</span> <span class="o">/*</span> <span class="o">/</span><span class="n">DCTDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_JBIG2</span> <span class="o">/*</span> <span class="o">/</span><span class="n">JBIG2Decode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_JPX</span> <span class="o">/*</span> <span class="o">/</span><span class="n">JPXDecode</span> <span class="o">*/</span> +<span class="n">PPSTREAM_CRYPT</span> <span class="o">/*</span> <span class="o">/</span><span class="n">Crypt</span> <span class="o">*/</span> +</pre></div> +</div> +<p>Params array keeps corresponding filter parameters (<code class="docutils literal notranslate"><span class="pre">/DecodeParms</span></code>) if present. <code class="docutils literal notranslate"><span class="pre">params</span></code> member is not NULL +if <code class="docutils literal notranslate"><span class="pre">count</span> <span class="pre">></span> <span class="pre">0</span></code> and the stream dict has <code class="docutils literal notranslate"><span class="pre">/DecodeParms</span></code> entry. Even if <code class="docutils literal notranslate"><span class="pre">params</span></code> is there, +for every N-th filter, <code class="docutils literal notranslate"><span class="pre">params[N]</span></code> may be NULL (corresponding to PDF <code class="docutils literal notranslate"><span class="pre">null</span></code>).</p> +<p><code class="docutils literal notranslate"><span class="pre">stream->filter</span></code> keeps the source stream filter information, which may not correspond to the result of stream readers +(<code class="docutils literal notranslate"><span class="pre">ppstream_first()</span></code>, <code class="docutils literal notranslate"><span class="pre">ppstream_next()</span></code>, <code class="docutils literal notranslate"><span class="pre">ppstream_all()</span></code>). The get the filters info relevant to the result from readers:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">ppstream_filter_info</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">ppstream_filter</span> <span class="o">*</span><span class="n">info</span><span class="p">,</span> <span class="nb">int</span> <span class="n">decode</span><span class="p">);</span> +</pre></div> +</div> +<p>The function fills <code class="docutils literal notranslate"><span class="pre">ppstream_filter</span></code> structure according to the expected result from stream readers (example 3 shows +how to use it to reconstruct <code class="docutils literal notranslate"><span class="pre">/Filter</span></code> and <code class="docutils literal notranslate"><span class="pre">/DecodeParms</span></code> when copying the stream to some other PDF).</p> +<p>To convert filter identifier (<code class="docutils literal notranslate"><span class="pre">ppstreamtp</span></code>) to a corresponding PDF filter name:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">ppstream_filter_name</span><span class="p">[];</span> +</pre></div> +</div> +<p>To covert <code class="docutils literal notranslate"><span class="pre">ppname</span></code> to filter identifier:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">ppstream_filter_type</span> <span class="p">(</span><span class="n">ppname</span> <span class="n">filtername</span><span class="p">,</span> <span class="n">ppstreamtp</span> <span class="o">*</span><span class="n">filtertype</span><span class="p">);</span> +<span class="o">//</span> <span class="n">returns</span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">sets</span> <span class="n">filtertype</span> <span class="k">if</span> <span class="n">filtername</span> <span class="ow">is</span> <span class="n">the</span> <span class="n">proper</span> <span class="nb">filter</span> <span class="n">name</span> +</pre></div> +</div> +<p>Additional information about the stream can be fetched from macros:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream_compressed</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span> <span class="o">/*</span> <span class="n">stream</span><span class="o">-></span><span class="n">flags</span> <span class="o">&</span> <span class="p">(</span><span class="n">PPSTREAM_FILTER</span><span class="o">|</span><span class="n">PPSTREAM_IMAGE</span><span class="p">)</span> <span class="o">*/</span> +<span class="n">ppstream_filtered</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span> <span class="o">/*</span> <span class="n">stream</span><span class="o">-></span><span class="n">flags</span> <span class="o">&</span> <span class="n">PPSTREAM_FILTER</span> <span class="o">*/</span> +<span class="n">ppstream_image</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span> <span class="o">/*</span> <span class="n">stream</span><span class="o">-></span><span class="n">flags</span> <span class="o">*</span> <span class="n">PPSTREAM_IMAGE</span> <span class="o">*/</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">stream->flags</span></code> is a binary sum of the following:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PPSTREAM_FILTER</span> <span class="o">/*</span> <span class="nb">set</span> <span class="n">iff</span> <span class="n">the</span> <span class="n">stream</span> <span class="n">filters</span> <span class="nb">list</span> <span class="n">has</span> <span class="n">one</span> <span class="n">of</span><span class="p">:</span> <span class="n">BASE16</span><span class="p">,</span> <span class="n">BASE85</span><span class="p">,</span> <span class="n">RUNLENGTH</span><span class="p">,</span> <span class="n">FLATE</span><span class="p">,</span> <span class="n">LZW</span> <span class="o">*/</span> +<span class="n">PPSTREAM_IMAGE</span> <span class="o">/*</span> <span class="nb">set</span> <span class="n">iff</span> <span class="n">the</span> <span class="n">stream</span> <span class="n">filters</span> <span class="nb">list</span> <span class="n">has</span> <span class="n">one</span> <span class="n">of</span><span class="p">:</span> <span class="n">CCITT</span><span class="p">,</span> <span class="n">DCT</span><span class="p">,</span> <span class="n">JBIG2</span><span class="p">,</span> <span class="n">JPX</span> <span class="o">*/</span> +<span class="n">PPSTREAM_ENCRYPTED</span> <span class="o">/*</span> <span class="nb">set</span> <span class="n">iff</span> <span class="n">the</span> <span class="n">stream</span> <span class="ow">is</span> <span class="n">encrypted</span> <span class="o">*/</span> +<span class="n">PPSTREAM_ENCRYPTED_OWN</span> <span class="o">/*</span> <span class="nb">set</span> <span class="n">iff</span> <span class="n">the</span> <span class="n">stream</span> <span class="n">has</span> <span class="n">own</span> <span class="n">CRYPT</span> <span class="nb">filter</span> <span class="o">*/</span> +</pre></div> +</div> +<p>Note that <code class="docutils literal notranslate"><span class="pre">PPSTREAM_COMPRESSED</span></code> is not there any longer, use <code class="docutils literal notranslate"><span class="pre">ppstream_compressed()</span></code> instead. +And there is some more, see <code class="docutils literal notranslate"><span class="pre">ppapi.h</span></code>.</p> +</div> +<div class="section" id="ref"> +<h2>Ref<a class="headerlink" href="#ref" title="Permalink to this headline">¶</a></h2> +<p>Indirect objects are represented as <code class="docutils literal notranslate"><span class="pre">ppref</span></code> structure. To get the object that the +reference refers to:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppref_obj</span><span class="p">(</span><span class="n">ppref</span> <span class="o">*</span><span class="n">ref</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">ppref</span></code> structure also keeps the reference number and version, a pointer to cross reference table it belongs +to and others, but I guess you won’t need anything but the referenced object. <code class="docutils literal notranslate"><span class="pre">pplib</span></code> parser resolves references +on-fly. So if there is a dict with indirect objects:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o"><<</span> + <span class="o">/</span><span class="n">Type</span> <span class="o">/</span><span class="n">Page</span> + <span class="o">/</span><span class="n">Resources</span> <span class="mi">123</span> <span class="mi">0</span> <span class="n">R</span> + <span class="o">...</span> +<span class="o">>></span> +</pre></div> +</div> +<p>the parser will produce <code class="docutils literal notranslate"><span class="pre">ppdict</span></code> with <code class="docutils literal notranslate"><span class="pre">Resources</span></code> key pointing the proper <code class="docutils literal notranslate"><span class="pre">ppref</span> <span class="pre">*</span></code> value. +If you need more, access <code class="docutils literal notranslate"><span class="pre">ppref</span></code> members:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">struct</span> <span class="n">ppref</span> <span class="p">{</span> + <span class="n">ppobj</span> <span class="nb">object</span><span class="p">;</span> <span class="o">//</span> <span class="n">target</span> <span class="nb">object</span> + <span class="n">ppuint</span> <span class="n">number</span><span class="p">,</span> <span class="n">version</span><span class="p">;</span> <span class="o">//</span> <span class="n">identifiers</span> + <span class="n">size_t</span> <span class="n">offset</span><span class="p">;</span> <span class="o">//</span> <span class="n">file</span> <span class="n">offset</span> <span class="p">(</span><span class="n">useless</span> <span class="k">for</span> <span class="n">you</span><span class="p">,</span> <span class="n">may</span> <span class="n">be</span> <span class="n">zero</span> <span class="k">for</span> <span class="n">compressed</span> <span class="n">objects</span><span class="p">)</span> + <span class="n">ppuint</span> <span class="n">length</span><span class="p">;</span> <span class="o">//</span> <span class="n">the</span> <span class="n">length</span> <span class="n">of</span> <span class="n">the</span> <span class="n">original</span> <span class="nb">object</span> <span class="n">data</span> + <span class="n">ppxref</span> <span class="o">*</span><span class="n">xref</span><span class="p">;</span> <span class="o">//</span> <span class="n">cross</span> <span class="n">reference</span> <span class="n">table</span> <span class="n">it</span> <span class="n">belongs</span> <span class="n">to</span> +<span class="p">};</span> +</pre></div> +</div> +</div> +<div class="section" id="xref"> +<h2>XRef<a class="headerlink" href="#xref" title="Permalink to this headline">¶</a></h2> +<p>Cross reference table is exposed as <code class="docutils literal notranslate"><span class="pre">ppxref</span></code> (incomplete type, you can only oprate on its pointer). +To get top document xref:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppxref</span> <span class="o">*</span> <span class="n">ppdoc_xref</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>To get previous (older) xref:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppxref</span> <span class="o">*</span> <span class="n">ppxref_prev</span> <span class="p">(</span><span class="n">ppxref</span> <span class="o">*</span><span class="n">xref</span><span class="p">);</span> +</pre></div> +</div> +<p>To find an object of a given refnumber:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppref</span> <span class="o">*</span> <span class="n">ppxref_find</span> <span class="p">(</span><span class="n">ppxref</span> <span class="o">*</span><span class="n">xref</span><span class="p">,</span> <span class="n">ppuint</span> <span class="n">refnumber</span><span class="p">);</span> +</pre></div> +</div> +<p>[Note: since pplib v0.98 in case of documents with incremental update, <code class="docutils literal notranslate"><span class="pre">ppxref_find()</span></code> returns +the newest available version of a given object rather than the object in a given body.]</p> +</div> +<div class="section" id="pdf"> +<h2>PDF<a class="headerlink" href="#pdf" title="Permalink to this headline">¶</a></h2> +<p>PDF document is represented as <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> structure (incomplete type, you can only operate on its pointer). +To load a document from file:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdoc</span> <span class="o">*</span> <span class="n">ppdoc_load</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">filename</span><span class="p">);</span> +</pre></div> +</div> +<p>To load a document from file handle:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdoc</span> <span class="o">*</span> <span class="n">ppdoc_filehandle</span> <span class="p">(</span><span class="n">FILE</span> <span class="o">*</span><span class="n">file</span><span class="p">,</span> <span class="nb">int</span> <span class="n">closefile</span><span class="p">);</span> <span class="o">//</span> <span class="n">closefile</span> <span class="mi">1</span> <span class="n">to</span> <span class="n">fclose</span><span class="p">()</span> <span class="n">on</span> <span class="n">end</span> +</pre></div> +</div> +<p>To load a document from memory data:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdoc</span> <span class="o">*</span> <span class="n">ppdoc_mem</span> <span class="p">(</span><span class="n">const</span> <span class="n">void</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">size</span><span class="p">);</span> +</pre></div> +</div> +<p>The data is assumed to be a buffer allocated with <code class="docutils literal notranslate"><span class="pre">malloc</span></code> - it is freed when destroying <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code>.</p> +<p>Both loaders returns <code class="docutils literal notranslate"><span class="pre">NULL</span></code> on failure.</p> +<p>To free <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> and all objects it refers to:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">ppdoc_free</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>So far we haven’t mention about any explicit object reclaimers. There are no dedicated <code class="docutils literal notranslate"><span class="pre">free</span></code> functions +for other objects. You don’t allocate or free objects yourself. <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> object is an owner of all +beings it refers to. It also means that every object described so far is alive as long as the containing +<code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> is alive.</p> +<p>To access main PDF dicts:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppdoc_trailer</span><span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">top</span> <span class="n">xref</span> <span class="n">trailer</span> <span class="nb">dict</span> +<span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppdoc_catalog</span><span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">catalog</span> <span class="n">referred</span> <span class="kn">from</span> <span class="nn">the</span> <span class="n">trailer</span> +<span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppdoc_info</span><span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">info</span> <span class="nb">dict</span> <span class="n">referred</span> <span class="kn">from</span> <span class="nn">the</span> <span class="n">trailer</span> +</pre></div> +</div> +<p>To get the PDF version:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">ppdoc_version_string</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> <span class="o">//</span> <span class="n">version</span> <span class="n">string</span> +<span class="nb">int</span> <span class="n">ppdoc_version_number</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">,</span> <span class="nb">int</span> <span class="o">*</span><span class="n">minor</span><span class="p">);</span> <span class="o">//</span> <span class="n">minor</span> <span class="ow">and</span> <span class="n">major</span> <span class="n">numbers</span> +</pre></div> +</div> +<p>To get the file size of the source PDF document:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">size_t</span> <span class="n">ppdoc_file_size</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>To get the number of objects in all xrefs:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppuint</span> <span class="n">ppdoc_objects</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>To get the approx usage of memory:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">size_t</span> <span class="n">ppdoc_memory</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">waste</span><span class="p">);</span> +</pre></div> +</div> +</div> +<div class="section" id="encryption"> +<h2>Encryption<a class="headerlink" href="#encryption" title="Permalink to this headline">¶</a></h2> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> handles encrypted (password protected) documents. If a document is encrypted, most of strings and streams are ciphered. +In that form they are unreadable and rather useless, you can’t even rewrite such strings/streams as-is to a different PDF output. +It is a common practise to <em>protect</em> documents with an empty password. Such documents remain readable in Acrobat (just opens them without prompting +for a password), but some features (eg. printing) may restricted by the application.</p> +<p>When <code class="docutils literal notranslate"><span class="pre">pplib</span></code> detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> proceeeds normally, providing +an access to decrypted strings and streams, as if they weren’t ciphered. If the document is protected with non-empty password, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> gives +a way to provide a password and proceed. Until you provide a password, <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> object returned by <code class="docutils literal notranslate"><span class="pre">ppdoc_load()</span></code> function has all object wntries +set to <code class="docutils literal notranslate"><span class="pre">null</span></code>.</p> +<p>After loading a document you should check encryption status with:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppcrypt_status</span> <span class="n">ppdoc_crypt_status</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">ppcrypt_status</span></code> (integer) may have the following values:</p> +<blockquote> +<div><code class="docutils literal notranslate"><span class="pre">PPCRYPT_NONE</span></code> - no encryption, go ahead +<code class="docutils literal notranslate"><span class="pre">PPCRYPT_DONE</span></code> - encryption present but password succeeded, go ahead +<code class="docutils literal notranslate"><span class="pre">PPCRYPT_PASS</span></code> - encryption present, need non-empty password +<code class="docutils literal notranslate"><span class="pre">PPCRYPT_FAIL</span></code> - invalid or unsupported encryption (eg. undocumented in pdf spec)</div></blockquote> +<p>If a password is needed, you can provide one with:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppcrypt_status</span> <span class="n">ppdoc_crypt_pass</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">,</span> <span class="n">const</span> <span class="n">void</span> <span class="o">*</span><span class="n">userpass</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">userpasslength</span><span class="p">,</span> + <span class="n">const</span> <span class="n">void</span> <span class="o">*</span><span class="n">ownerpass</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">ownerpasslength</span><span class="p">);</span> +</pre></div> +</div> +<p>Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough +to know that having one of them is enough to decrypt the document. If you know the password, you probably mean +<code class="docutils literal notranslate"><span class="pre">userpass</span></code>, in which case you should put <code class="docutils literal notranslate"><span class="pre">NULL</span></code> as <code class="docutils literal notranslate"><span class="pre">ownerpass</span></code>. The function returns <code class="docutils literal notranslate"><span class="pre">PPCRYPT_DONE</span></code> if the password +succeeds and the previous status otherwise. Your custom loader function may look like that:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">;</span> +<span class="n">pdf</span> <span class="o">=</span> <span class="n">ppdoc_load</span><span class="p">(</span><span class="s2">"file.pdf"</span><span class="p">);</span> +<span class="k">if</span> <span class="p">(</span><span class="n">pdf</span> <span class="o">==</span> <span class="n">NULL</span><span class="p">)</span> + <span class="k">return</span> <span class="n">NULL</span><span class="p">;</span> +<span class="n">switch</span> <span class="p">(</span><span class="n">ppdoc_crypt_status</span><span class="p">(</span><span class="n">pdf</span><span class="p">))</span> +<span class="p">{</span> + <span class="n">case</span> <span class="n">PPCRYPT_NONE</span><span class="p">:</span> + <span class="n">case</span> <span class="n">PPCRYPT_DONE</span><span class="p">:</span> + <span class="k">return</span> <span class="n">pdf</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPCRYPT_PASS</span><span class="p">:</span> + <span class="k">if</span> <span class="p">(</span><span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="s2">"dummy"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span> <span class="o">||</span> + <span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"dummy"</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span><span class="p">)</span> + <span class="k">return</span> <span class="n">pdf</span><span class="p">;</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">"sorry, password needed</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> + <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span> + <span class="k">return</span> <span class="n">NULL</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPCRYPT_FAIL</span><span class="p">:</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">"sorry, encryption failed</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> + <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span> + <span class="k">return</span> <span class="n">NULL</span><span class="p">;</span> +<span class="p">}</span> +</pre></div> +</div> +<p>[If you get <code class="docutils literal notranslate"><span class="pre">PPCRYPT_FAIL</span></code> it might mean <em>I failed</em>, so treat as a bug.]</p> +<p>If you’d like to know what permissions are given/restricted to encrypted document:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppint</span> <span class="n">ppdoc_permissions</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>Returned value can be queried with the following binary flags (you can verify with Acrobat <em>File -> Properties -> Security</em> tab):</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PPDOC_ALLOW_PRINT</span> <span class="o">//</span> <span class="n">printing</span> +<span class="n">PPDOC_ALLOW_MODIFY</span> <span class="o">//</span> <span class="n">filling</span> <span class="n">form</span> <span class="n">fields</span><span class="p">,</span> <span class="n">signing</span><span class="p">,</span> <span class="n">creating</span> <span class="n">template</span> <span class="n">pages</span> +<span class="n">PPDOC_ALLOW_COPY</span> <span class="o">//</span> <span class="n">copying</span><span class="p">,</span> <span class="n">copying</span> <span class="k">for</span> <span class="n">accessibility</span> +<span class="n">PPDOC_ALLOW_ANNOTS</span> <span class="o">//</span> <span class="n">filling</span> <span class="n">form</span> <span class="n">fields</span><span class="p">,</span> <span class="n">copying</span><span class="p">,</span> <span class="n">signing</span> +<span class="n">PPDOC_ALLOW_EXTRACT</span> <span class="o">//</span> <span class="n">contents</span> <span class="n">copying</span> <span class="k">for</span> <span class="n">accessibility</span> +<span class="n">PPDOC_ALLOW_ASSEMBLY</span> <span class="o">//</span> <span class="p">(</span><span class="n">no</span> <span class="n">effect</span><span class="p">)</span> +<span class="n">PPDOC_ALLOW_PRINT_HIRES</span> <span class="o">//</span> <span class="p">(</span><span class="n">no</span> <span class="n">effect</span><span class="p">)</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> does absolutelly nothing with permissions, it cares only to decrypt the document. As mentioned, encryption applies to strings +and streams. <code class="docutils literal notranslate"><span class="pre">pplib</span></code> decrypt strings when parsing document objects, so the result you get is <em>normal</em> (not ciphered). +Streams are decrypted whenever you access them. Even if you ask for a raw stream data, you’ll get a raw (compressed) stream, but decrypted. +So except the check to <code class="docutils literal notranslate"><span class="pre">ppdoc_crypt_status()</span></code>, you shouldn’t bother about encryption.</p> +<p>In encrypted documents most of streams are encrypted. To check if a given stream is encrypted:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream_encrypted</span><span class="p">(</span><span class="n">stream</span><span class="p">)</span> <span class="o">//</span> <span class="n">macro</span><span class="p">,</span> <span class="n">returns</span> <span class="n">non</span><span class="o">-</span><span class="n">zero</span> <span class="k">if</span> <span class="n">encrypted</span> +</pre></div> +</div> +<p>Encryption is independent from compression, don’t confuse with <code class="docutils literal notranslate"><span class="pre">ppstream_compressed()</span></code></p> +</div> +<div class="section" id="pages"> +<h2>Pages<a class="headerlink" href="#pages" title="Permalink to this headline">¶</a></h2> +<p>Several helpers to deal with pages. To get the number of pages:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppuint</span> <span class="n">ppdoc_page_count</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>To access the root pages tree node:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppref</span> <span class="o">*</span> <span class="n">ppdoc_pages</span><span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>To get the page reference at a given index:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppref</span> <span class="o">*</span> <span class="n">ppdoc_page</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">,</span> <span class="n">ppuint</span> <span class="n">index</span><span class="p">);</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">index</span></code> is a page number. First page has number 1. For index out of bounds <code class="docutils literal notranslate"><span class="pre">ppdoc_page()</span></code> returns NULL. +Iterating over pages using index from 1 to <code class="docutils literal notranslate"><span class="pre">ppdoc_page_count()</span></code> and calling <code class="docutils literal notranslate"><span class="pre">ppdoc_page()</span></code> on each iteration +would be suboptimal. Here is a dedicted iterator for this:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppref</span> <span class="o">*</span> <span class="n">ppdoc_first_page</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +<span class="n">ppref</span> <span class="o">*</span> <span class="n">ppdoc_next_page</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> +</pre></div> +</div> +<p>The iterator in use:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">;</span> +<span class="n">ppref</span> <span class="o">*</span><span class="n">ref</span><span class="p">;</span> +<span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">;</span> +<span class="nb">int</span> <span class="n">pageno</span><span class="p">;</span> + +<span class="n">pdf</span> <span class="o">=</span> <span class="n">ppdoc_load</span><span class="p">(</span><span class="s2">"file.pdf"</span><span class="p">);</span> +<span class="k">for</span> <span class="p">(</span><span class="n">ref</span> <span class="o">=</span> <span class="n">ppdoc_first_page</span><span class="p">(</span><span class="n">pdf</span><span class="p">),</span> <span class="n">pageno</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">ref</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">;</span> <span class="n">ref</span> <span class="o">=</span> <span class="n">ppdoc_next_page</span><span class="p">(</span><span class="n">pdf</span><span class="p">),</span> <span class="o">++</span><span class="n">pageno</span><span class="p">)</span> +<span class="p">{</span> + <span class="nb">dict</span> <span class="o">=</span> <span class="n">ppref_obj</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span><span class="o">-></span><span class="nb">dict</span><span class="p">;</span> <span class="o">//</span> <span class="n">take</span> <span class="k">for</span> <span class="n">granted</span> <span class="n">it</span> <span class="ow">is</span> <span class="n">a</span> <span class="nb">dict</span> + <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">the</span> <span class="n">page</span> <span class="nb">dict</span> +<span class="p">}</span> +</pre></div> +</div> +<p>Functions related to pages return <code class="docutils literal notranslate"><span class="pre">ppref</span> <span class="pre">*</span></code> ensured to contain dict object, so you don’t need sanity +type checks here.</p> +</div> +<div class="section" id="contents"> +<h2>Contents<a class="headerlink" href="#contents" title="Permalink to this headline">¶</a></h2> +<p>PDF page contents can be given as a stream or array of streams. Here is a convenience iterator over page +contents streams:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppstream</span> <span class="o">*</span> <span class="n">ppcontents_first</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">);</span> +<span class="n">ppstream</span> <span class="o">*</span> <span class="n">ppcontents_next</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">);</span> +</pre></div> +</div> +<p>A complete example of contents stream parser use is given below (example 2). +But before we get there, we need to introduce <code class="docutils literal notranslate"><span class="pre">ppcontext</span></code> object. Conceptually, +<code class="docutils literal notranslate"><span class="pre">ppcontext</span></code> is an owner (memory handler) of objects created on demand (beyond the <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code>). +So far used only with contents stream parser, which might produce quite some data that we want +to release just after used. To create a new context:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pcontext</span> <span class="o">*</span> <span class="n">ppcontext_new</span> <span class="p">(</span><span class="n">void</span><span class="p">);</span> +</pre></div> +</div> +<p>It initializes a new context and its internal memory heap, taking about 64kB on start. After that, +the context is ready to produce objects (contents parsing functions below). Once objects produced +from a given context are no longer needed:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">ppcontext_done</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">);</span> +</pre></div> +</div> +<p>It restores the context to its initial state, as after <code class="docutils literal notranslate"><span class="pre">ppcontext_new()</span></code>. It means that the context +is ready to produce another bunch of beings (in the example below, all objects from the next page contents). +Once the context is not needed anymore:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">ppcontext_free</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">);</span> +</pre></div> +</div> +<p>Now, contents stream parser functions take the context as an argument. Iterator form of contents stream parser +that allows to process the contents operator by operator:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppcontents_first_op</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">psize</span><span class="p">,</span> <span class="n">ppname</span> <span class="o">*</span><span class="n">pname</span><span class="p">);</span> +<span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppcontents_next_op</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">psize</span><span class="p">,</span> <span class="n">ppname</span> <span class="o">*</span><span class="n">pname</span><span class="p">);</span> +</pre></div> +</div> +<p>Returned <code class="docutils literal notranslate"><span class="pre">ppobj</span> <span class="pre">*</span></code> is a pointer to operands list. <code class="docutils literal notranslate"><span class="pre">*psize</span></code> is the number of operands on stack. +The operator itself is stored as <code class="docutils literal notranslate"><span class="pre">*pname</span></code>.</p> +<p>To parse the entire contents stream at once with no stop at every operator:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppcontents_parse</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">psize</span><span class="p">);</span> +</pre></div> +</div> +<p>Returns probably quite long list of all parsed objects (operands and operatos) in one piece. +The number of objects is stored to <code class="docutils literal notranslate"><span class="pre">*psize</span></code>.</p> +<p>[Contents may contain so called inline images, that breaks a simple scheme of operands / operator syntax:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">BI</span> <span class="o"><</span><span class="n">keyval</span> <span class="n">pairs</span><span class="o">></span> <span class="n">ID</span> <span class="o"><</span><span class="n">binary</span> <span class="n">image</span> <span class="n">data</span><span class="o">></span> <span class="n">EI</span> +</pre></div> +</div> +<p>Contents parser treats this genuine triplet as a single piece, producing two operands (dict and string) +followed by <code class="docutils literal notranslate"><span class="pre">EI</span></code> operator name.]</p> +</div> +<div class="section" id="boxes"> +<h2>Boxes<a class="headerlink" href="#boxes" title="Permalink to this headline">¶</a></h2> +<p>Boxes (rectangles) in PDF are roughly 4-number arrays, but with a special intent. +<code class="docutils literal notranslate"><span class="pre">pplib</span></code> provides a basic interface for these special arrays:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span> + <span class="n">ppnum</span> <span class="n">lx</span><span class="p">,</span> <span class="n">ly</span><span class="p">,</span> <span class="n">rx</span><span class="p">,</span> <span class="n">ry</span><span class="p">;</span> +<span class="p">}</span> <span class="n">pprect</span><span class="p">;</span> +</pre></div> +</div> +<p>This type is used only by helper functions - PDF parser is not aware of the rectangle type. +To convert <code class="docutils literal notranslate"><span class="pre">pparray</span></code> to <code class="docutils literal notranslate"><span class="pre">pprect</span></code>:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pprect</span> <span class="o">*</span> <span class="n">pparray_to_rect</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">pprect</span> <span class="o">*</span><span class="n">rect</span><span class="p">);</span> <span class="o">//</span> <span class="n">returns</span> <span class="n">rect</span> <span class="ow">or</span> <span class="n">NULL</span> +</pre></div> +</div> +<p>In example:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pprect</span> <span class="n">rect</span><span class="p">;</span> +<span class="k">if</span> <span class="p">(</span><span class="n">pparray_to_rect</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="o">&</span><span class="n">rect</span><span class="p">)</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">)</span> + <span class="p">;</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">rect</span> +</pre></div> +</div> +<p>To get some image bounding box:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pprect</span> <span class="o">*</span> <span class="n">ppdict_get_rect</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">pprect</span> <span class="o">*</span><span class="n">rect</span><span class="p">);</span> +<span class="o">//</span> <span class="n">eg</span><span class="o">.</span> <span class="n">ppdict_get_rect</span><span class="p">(</span><span class="n">imagedict</span><span class="p">,</span> <span class="s2">"BBox"</span><span class="p">,</span> <span class="o">&</span><span class="n">rect</span><span class="p">)</span> +</pre></div> +</div> +<p>To get some page box:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pprect</span> <span class="o">*</span> <span class="n">ppdict_get_box</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">pprect</span> <span class="o">*</span><span class="n">rect</span><span class="p">);</span> +<span class="o">//</span> <span class="n">eg</span><span class="o">.</span> <span class="n">ppdict_get_box</span><span class="p">(</span><span class="n">pagedict</span><span class="p">,</span> <span class="s2">"MediaBox"</span><span class="p">,</span> <span class="o">&</span><span class="n">rect</span><span class="p">)</span> +</pre></div> +</div> +<p>The later not only checks the pagedict, but also goes through parent page nodes.</p> +</div> +<div class="section" id="transforms"> +<h2>Transforms<a class="headerlink" href="#transforms" title="Permalink to this headline">¶</a></h2> +<p>Transformations are given as 6-number arrays, but with a special intent. +<code class="docutils literal notranslate"><span class="pre">pplib</span></code> provides a basic interface for these special arrays:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span> + <span class="n">ppnum</span> <span class="n">xx</span><span class="p">,</span> <span class="n">xy</span><span class="p">,</span> <span class="n">yx</span><span class="p">,</span> <span class="n">yy</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">;</span> +<span class="p">}</span> <span class="n">ppmatrix</span><span class="p">;</span> +</pre></div> +</div> +<p>This type is used only by helper functions - PDF parser is not aware of the matrix type. +To convert <code class="docutils literal notranslate"><span class="pre">pparray</span></code> to <code class="docutils literal notranslate"><span class="pre">ppmatrix</span></code>:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppmatrix</span> <span class="o">*</span> <span class="n">pparray_to_matrix</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">ppmatrix</span> <span class="o">*</span><span class="n">matrix</span><span class="p">);</span> +</pre></div> +</div> +<p>In example:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppmatrix</span> <span class="n">matrix</span><span class="p">;</span> +<span class="k">if</span> <span class="p">(</span><span class="n">pparray_to_matrix</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="o">&</span><span class="n">matrix</span><span class="p">)</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">)</span> + <span class="p">;</span> <span class="o">//</span> <span class="n">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">matrix</span> +</pre></div> +</div> +<p>To get the matrix from dict:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppmatrix</span> <span class="o">*</span> <span class="n">ppdict_get_matrix</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppmatrix</span> <span class="o">*</span><span class="n">matrix</span><span class="p">);</span> +<span class="o">//</span> <span class="n">eg</span><span class="o">.</span> <span class="n">ppdict_get_matrix</span><span class="p">(</span><span class="n">imagedict</span><span class="p">,</span> <span class="s2">"Matrix"</span><span class="p">,</span> <span class="o">&</span><span class="n">matrix</span><span class="p">)</span> +</pre></div> +</div> +</div> +<div class="section" id="errors-handling"> +<h2>Errors handling<a class="headerlink" href="#errors-handling" title="Permalink to this headline">¶</a></h2> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> is not verbose, but might happen that it needs to log some error message, eg. when parsing +of some PDF boject fails due to invalid offsets. By default, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> prints the message to stdout, eg.:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">invalid</span> <span class="mi">123</span> <span class="mi">0</span> <span class="n">R</span> <span class="nb">object</span> <span class="n">at</span> <span class="n">offset</span> <span class="mi">123123</span> +</pre></div> +</div> +<p>To replace the default logger, you can provide your own:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">pplog_callback</span> <span class="p">(</span><span class="n">pplogger_callback</span> <span class="n">logger</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">alien</span><span class="p">);</span> +</pre></div> +</div> +<p><code class="docutils literal notranslate"><span class="pre">pplogger_callback</span></code> is a function:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">your_callback</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">message</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">alien</span><span class="p">);</span> +</pre></div> +</div> +<p>In example, to redirect messages to stderr you may define a function:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">void</span> <span class="n">your_callback</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">message</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">alien</span><span class="p">)</span> +<span class="p">{</span> + <span class="n">fprintf</span><span class="p">((</span><span class="n">FILE</span> <span class="o">*</span><span class="p">)</span><span class="n">alien</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">ooops: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">message</span><span class="p">);</span> +<span class="p">}</span> +</pre></div> +</div> +<p>Then set the callback somewhere before loading documents:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pplog_callback</span><span class="p">(</span><span class="n">your_callback</span><span class="p">,</span> <span class="n">stderr</span><span class="p">);</span> +</pre></div> +</div> +<p>(example 2 uses that).</p> +<p>To set the default log messages prefix, eg. <code class="docutils literal notranslate"><span class="pre">pplib:</span></code>, use:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">int</span> <span class="n">pplog_prefix</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">prefix</span><span class="p">)</span> +</pre></div> +</div> +<p>Default is empty. The function succeeds if provided prefix is reasonably short (less then 32 bytes).</p> +</div> +</div> + + + </div> + </div> + </div> + <div class="clearer"></div> + </div> + <div class="related" role="navigation" aria-label="related navigation"> + <h3>Navigation</h3> + <ul> + <li class="right" style="margin-right: 10px"> + <a href="genindex.html" title="General Index" + >index</a></li> + <li class="right" > + <a href="ppapi-1.x.html" title="pplib 1.x" + >next</a> |</li> + <li class="right" > + <a href="ppnew.html" title="1.x vs 2.x" + >previous</a> |</li> + <li class="nav-item nav-item-0"><a href="pplib.html">pplib 0.1 documentation</a> »</li> + </ul> + </div> + <div class="footer" role="contentinfo"> + © Copyright 2019, p.jackowski@gust.org.pl. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5. + </div> + </body> +</html>
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/ppapi.html b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppapi.html index 8ba0febca93..2a5de7a6b1c 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/ppapi.html +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppapi.html @@ -9,10 +9,12 @@ <title>pplib — pplib 0.1 documentation</title> <link rel="stylesheet" href="_static/bizstyle.css" type="text/css" /> <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> - <script type="text/javascript" src="_static/documentation_options.js"></script> + + <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> <script type="text/javascript" src="_static/jquery.js"></script> <script type="text/javascript" src="_static/underscore.js"></script> <script type="text/javascript" src="_static/doctools.js"></script> + <script async="async" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> <script type="text/javascript" src="_static/bizstyle.js"></script> <link rel="index" title="Index" href="genindex.html" /> <link rel="search" title="Search" href="search.html" /> @@ -40,7 +42,7 @@ </div> <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> <div class="sphinxsidebarwrapper"> - <h3><a href="pplib.html">Table Of Contents</a></h3> + <h3><a href="pplib.html">Table of Contents</a></h3> <ul> <li><a class="reference internal" href="#"><code class="docutils literal notranslate"><span class="pre">pplib</span></code></a></li> <li><a class="reference internal" href="#c-api">C-API</a><ul> @@ -1022,7 +1024,7 @@ of some PDF boject fails due to invalid offsets. By default, <code class="docuti </div> <div class="footer" role="contentinfo"> © Copyright 2018, p.jackowski@gust.org.pl. - Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.4. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.1. </div> </body> </html>
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/ppcode.html b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppcode.html index e65000d0fd5..8645450d8ec 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/ppcode.html +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppcode.html @@ -9,14 +9,16 @@ <title>Examples — pplib 0.1 documentation</title> <link rel="stylesheet" href="_static/bizstyle.css" type="text/css" /> <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> - <script type="text/javascript" src="_static/documentation_options.js"></script> + + <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> <script type="text/javascript" src="_static/jquery.js"></script> <script type="text/javascript" src="_static/underscore.js"></script> <script type="text/javascript" src="_static/doctools.js"></script> + <script type="text/javascript" src="_static/language_data.js"></script> <script type="text/javascript" src="_static/bizstyle.js"></script> <link rel="index" title="Index" href="genindex.html" /> <link rel="search" title="Search" href="search.html" /> - <link rel="prev" title="pplib" href="ppapi.html" /> + <link rel="prev" title="pplib 1.x" href="ppapi-1.x.html" /> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <!--[if lt IE 9]> <script type="text/javascript" src="_static/css3-mediaqueries.js"></script> @@ -29,14 +31,14 @@ <a href="genindex.html" title="General Index" accesskey="I">index</a></li> <li class="right" > - <a href="ppapi.html" title="pplib" + <a href="ppapi-1.x.html" title="pplib 1.x" accesskey="P">previous</a> |</li> <li class="nav-item nav-item-0"><a href="pplib.html">pplib 0.1 documentation</a> »</li> </ul> </div> <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> <div class="sphinxsidebarwrapper"> - <h3><a href="pplib.html">Table Of Contents</a></h3> + <h3><a href="pplib.html">Table of Contents</a></h3> <ul> <li><a class="reference internal" href="#">Examples</a><ul> <li><a class="reference internal" href="#example-1">Example 1</a></li> @@ -54,14 +56,21 @@ <li><a class="reference internal" href="#v1-02">v1.02</a></li> <li><a class="reference internal" href="#v1-03">v1.03</a></li> <li><a class="reference internal" href="#v1-04">v1.04</a></li> +<li><a class="reference internal" href="#v1-05">v1.05</a></li> +<li><a class="reference internal" href="#v2-00">v2.00</a></li> +<li><a class="reference internal" href="#v2-01">v2.01</a></li> +<li><a class="reference internal" href="#v2-02">v2.02</a></li> +<li><a class="reference internal" href="#v2-03">v2.03</a></li> +<li><a class="reference internal" href="#v2-04">v2.04</a></li> +<li><a class="reference internal" href="#v2-05">v2.05</a></li> </ul> </li> <li><a class="reference internal" href="#todo">TODO</a></li> </ul> <h4>Previous topic</h4> - <p class="topless"><a href="ppapi.html" - title="previous chapter"><code class="docutils literal notranslate"><span class="pre">pplib</span></code></a></p> + <p class="topless"><a href="ppapi-1.x.html" + title="previous chapter"><code class="docutils literal notranslate"><span class="pre">pplib</span></code> 1.x</a></p> <div role="note" aria-label="source link"> <h3>This Page</h3> <ul class="this-page-menu"> @@ -96,6 +105,7 @@ <div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="c1">#include <stdio.h></span> <span class="c1">#include "ppapi.h"</span> +<span class="c1">#include "util/utiliof.h"</span> <span class="n">static</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">sizenum</span> <span class="p">(</span><span class="n">size_t</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> @@ -111,38 +121,38 @@ <span class="n">static</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">crypt_info</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">)</span> <span class="p">{</span> - <span class="n">switch</span> <span class="p">(</span><span class="n">ppdoc_crypt_status</span><span class="p">(</span><span class="n">pdf</span><span class="p">))</span> - <span class="p">{</span> - <span class="n">case</span> <span class="n">PPCRYPT_NONE</span><span class="p">:</span> - <span class="k">return</span> <span class="s2">"none"</span><span class="p">;</span> - <span class="n">case</span> <span class="n">PPCRYPT_DONE</span><span class="p">:</span> - <span class="k">return</span> <span class="s2">"empty password"</span><span class="p">;</span> - <span class="n">case</span> <span class="n">PPCRYPT_PASS</span><span class="p">:</span> - <span class="k">return</span> <span class="s2">"nonempty password"</span><span class="p">;</span> - <span class="n">default</span><span class="p">:</span> - <span class="k">break</span><span class="p">;</span> - <span class="p">}</span> - <span class="k">return</span> <span class="s2">"this shouldn't happen"</span><span class="p">;</span> + <span class="n">switch</span> <span class="p">(</span><span class="n">ppdoc_crypt_status</span><span class="p">(</span><span class="n">pdf</span><span class="p">))</span> + <span class="p">{</span> + <span class="n">case</span> <span class="n">PPCRYPT_NONE</span><span class="p">:</span> + <span class="k">return</span> <span class="s2">"none"</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPCRYPT_DONE</span><span class="p">:</span> + <span class="k">return</span> <span class="s2">"empty password"</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPCRYPT_PASS</span><span class="p">:</span> + <span class="k">return</span> <span class="s2">"nonempty password"</span><span class="p">;</span> + <span class="n">default</span><span class="p">:</span> + <span class="k">break</span><span class="p">;</span> + <span class="p">}</span> + <span class="k">return</span> <span class="s2">"this shouldn't happen"</span><span class="p">;</span> <span class="p">}</span> <span class="n">static</span> <span class="n">void</span> <span class="n">print_info</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">)</span> <span class="p">{</span> <span class="n">ppdict</span> <span class="o">*</span><span class="n">info</span><span class="p">;</span> - <span class="n">ppstring</span> <span class="n">creator</span><span class="p">,</span> <span class="n">producer</span><span class="p">;</span> + <span class="n">ppstring</span> <span class="o">*</span><span class="n">creator</span><span class="p">,</span> <span class="o">*</span><span class="n">producer</span><span class="p">;</span> <span class="n">size_t</span> <span class="n">memused</span><span class="p">,</span> <span class="n">memwaste</span><span class="p">;</span> <span class="k">if</span> <span class="p">((</span><span class="n">info</span> <span class="o">=</span> <span class="n">ppdoc_info</span><span class="p">(</span><span class="n">pdf</span><span class="p">))</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">((</span><span class="n">creator</span> <span class="o">=</span> <span class="n">ppdict_rget_string</span><span class="p">(</span><span class="n">info</span><span class="p">,</span> <span class="s2">"Creator"</span><span class="p">))</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">)</span> - <span class="n">printf</span><span class="p">(</span><span class="s2">" creator: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">ppstring_decoded</span><span class="p">(</span><span class="n">creator</span><span class="p">));</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">" creator: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">ppstring_decoded_data</span><span class="p">(</span><span class="n">creator</span><span class="p">));</span> <span class="k">if</span> <span class="p">((</span><span class="n">producer</span> <span class="o">=</span> <span class="n">ppdict_rget_string</span><span class="p">(</span><span class="n">info</span><span class="p">,</span> <span class="s2">"Producer"</span><span class="p">))</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">)</span> - <span class="n">printf</span><span class="p">(</span><span class="s2">" producer: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">ppstring_decoded</span><span class="p">(</span><span class="n">producer</span><span class="p">));</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">" producer: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">ppstring_decoded_data</span><span class="p">(</span><span class="n">producer</span><span class="p">));</span> <span class="p">}</span> <span class="n">printf</span><span class="p">(</span><span class="s2">" version: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">ppdoc_version_string</span><span class="p">(</span><span class="n">pdf</span><span class="p">));</span> <span class="n">printf</span><span class="p">(</span><span class="s2">" protection: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">crypt_info</span><span class="p">(</span><span class="n">pdf</span><span class="p">));</span> <span class="n">printf</span><span class="p">(</span><span class="s2">" filesize: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">sizenum</span><span class="p">(</span><span class="n">ppdoc_file_size</span><span class="p">(</span><span class="n">pdf</span><span class="p">)));</span> - <span class="n">printf</span><span class="p">(</span><span class="s2">" objects: "</span> <span class="n">PPUINTF</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">ppdoc_objects</span><span class="p">(</span><span class="n">pdf</span><span class="p">));</span> - <span class="n">printf</span><span class="p">(</span><span class="s2">" pagecount: "</span> <span class="n">PPUINTF</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">ppdoc_page_count</span><span class="p">(</span><span class="n">pdf</span><span class="p">));</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">" objects: </span><span class="si">%lu</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="p">(</span><span class="n">unsigned</span> <span class="n">long</span><span class="p">)</span><span class="n">ppdoc_objects</span><span class="p">(</span><span class="n">pdf</span><span class="p">));</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">" pagecount: </span><span class="si">%lu</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="p">(</span><span class="n">unsigned</span> <span class="n">long</span><span class="p">)</span><span class="n">ppdoc_page_count</span><span class="p">(</span><span class="n">pdf</span><span class="p">));</span> <span class="n">memused</span> <span class="o">=</span> <span class="n">ppdoc_memory</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="o">&</span><span class="n">memwaste</span><span class="p">);</span> <span class="n">printf</span><span class="p">(</span><span class="s2">" memused: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">sizenum</span><span class="p">(</span><span class="n">memused</span><span class="p">));</span> <span class="n">printf</span><span class="p">(</span><span class="s2">" memwaste: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">sizenum</span><span class="p">(</span><span class="n">memwaste</span><span class="p">));</span> @@ -150,9 +160,9 @@ <span class="n">static</span> <span class="nb">int</span> <span class="n">usage</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">argv0</span><span class="p">)</span> <span class="p">{</span> - <span class="n">printf</span><span class="p">(</span><span class="s2">"pplib "</span> <span class="n">pplib_version</span> <span class="s2">", "</span> <span class="n">pplib_author</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> - <span class="n">printf</span><span class="p">(</span><span class="s2">"usage: </span><span class="si">%s</span><span class="s2"> file1.pdf file2.pdf ...</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">argv0</span><span class="p">);</span> - <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">"pplib "</span> <span class="n">pplib_version</span> <span class="s2">", "</span> <span class="n">pplib_author</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">"usage: </span><span class="si">%s</span><span class="s2"> file1.pdf file2.pdf ...</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">argv0</span><span class="p">);</span> + <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> <span class="nb">int</span> <span class="n">main</span> <span class="p">(</span><span class="nb">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> @@ -160,6 +170,8 @@ <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">filepath</span><span class="p">;</span> <span class="nb">int</span> <span class="n">a</span><span class="p">;</span> <span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">;</span> + <span class="n">const</span> <span class="n">void</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span> + <span class="n">size_t</span> <span class="n">size</span><span class="p">;</span> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o"><</span> <span class="mi">2</span><span class="p">)</span> <span class="k">return</span> <span class="n">usage</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> @@ -176,6 +188,21 @@ <span class="n">printf</span><span class="p">(</span><span class="s2">"done.</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> <span class="n">print_info</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span> <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span> + <span class="o">/*</span> <span class="n">now</span> <span class="n">loading</span> <span class="kn">from</span> <span class="nn">memory</span> <span class="n">buffer</span> <span class="o">*/</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">"loading </span><span class="si">%s</span><span class="s2"> from mem buffer... "</span><span class="p">,</span> <span class="n">filepath</span><span class="p">);</span> + <span class="n">data</span> <span class="o">=</span> <span class="n">iof_copy_file_data</span><span class="p">(</span><span class="n">filepath</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">);</span> + <span class="k">if</span> <span class="p">(</span><span class="n">data</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">pdf</span> <span class="o">=</span> <span class="n">ppdoc_mem</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span> + <span class="k">if</span> <span class="p">(</span><span class="n">pdf</span> <span class="o">==</span> <span class="n">NULL</span><span class="p">)</span> + <span class="p">{</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">"failed</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> + <span class="k">continue</span><span class="p">;</span> + <span class="p">}</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">"done.</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> + <span class="o">//</span><span class="n">print_info</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span> + <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span> + <span class="p">}</span> <span class="p">}</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> @@ -189,6 +216,7 @@ <span class="c1">#include <assert.h></span> <span class="c1">#include "ppapi.h"</span> +<span class="o">/*</span> <span class="n">static</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">get_file_name</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">path</span><span class="p">)</span> <span class="p">{</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">fn</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> @@ -197,6 +225,7 @@ <span class="n">fn</span> <span class="o">=</span> <span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="k">return</span> <span class="n">fn</span><span class="p">;</span> <span class="p">}</span> +<span class="o">*/</span> <span class="n">static</span> <span class="n">void</span> <span class="n">box_info</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="n">pagedict</span><span class="p">,</span> <span class="n">FILE</span> <span class="o">*</span><span class="n">fh</span><span class="p">)</span> <span class="p">{</span> @@ -210,21 +239,19 @@ <span class="n">static</span> <span class="nb">int</span> <span class="n">usage</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">argv0</span><span class="p">)</span> <span class="p">{</span> - <span class="n">printf</span><span class="p">(</span><span class="s2">"pplib "</span> <span class="n">pplib_version</span> <span class="s2">", "</span> <span class="n">pplib_author</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> - <span class="n">printf</span><span class="p">(</span><span class="s2">"usage: </span><span class="si">%s</span><span class="s2"> file1.pdf file2.pdf ...</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">argv0</span><span class="p">);</span> - <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">"pplib "</span> <span class="n">pplib_version</span> <span class="s2">", "</span> <span class="n">pplib_author</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">"usage: </span><span class="si">%s</span><span class="s2"> file1.pdf file2.pdf ...</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">argv0</span><span class="p">);</span> + <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> -<span class="c1">#define OUTDIR "."</span> - <span class="n">static</span> <span class="n">void</span> <span class="n">log_callback</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">message</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">alien</span><span class="p">)</span> <span class="p">{</span> - <span class="n">fprintf</span><span class="p">((</span><span class="n">FILE</span> <span class="o">*</span><span class="p">)</span><span class="n">alien</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">ooops: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">message</span><span class="p">);</span> + <span class="n">fprintf</span><span class="p">((</span><span class="n">FILE</span> <span class="o">*</span><span class="p">)</span><span class="n">alien</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">ooops: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">message</span><span class="p">);</span> <span class="p">}</span> <span class="nb">int</span> <span class="n">main</span> <span class="p">(</span><span class="nb">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span> - <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">filepath</span><span class="p">,</span> <span class="o">*</span><span class="n">filename</span><span class="p">;</span> + <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">filepath</span><span class="p">;</span> <span class="nb">int</span> <span class="n">a</span><span class="p">;</span> <span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">;</span> <span class="n">ppref</span> <span class="o">*</span><span class="n">pageref</span><span class="p">;</span> @@ -237,7 +264,7 @@ <span class="n">size_t</span> <span class="n">size</span><span class="p">;</span> <span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">;</span> <span class="n">ppobj</span> <span class="o">*</span><span class="n">obj</span><span class="p">;</span> - <span class="n">ppname</span> <span class="n">op</span><span class="p">;</span> + <span class="n">ppname</span> <span class="o">*</span><span class="n">op</span><span class="p">;</span> <span class="n">size_t</span> <span class="n">operators</span><span class="p">;</span> <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o"><</span> <span class="mi">2</span><span class="p">)</span> @@ -258,22 +285,21 @@ <span class="n">printf</span><span class="p">(</span><span class="s2">"done.</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> <span class="n">switch</span> <span class="p">(</span><span class="n">ppdoc_crypt_status</span><span class="p">(</span><span class="n">pdf</span><span class="p">))</span> <span class="p">{</span> - <span class="n">case</span> <span class="n">PPCRYPT_NONE</span><span class="p">:</span> - <span class="n">case</span> <span class="n">PPCRYPT_DONE</span><span class="p">:</span> - <span class="k">break</span><span class="p">;</span> - <span class="n">case</span> <span class="n">PPCRYPT_PASS</span><span class="p">:</span> - <span class="k">if</span> <span class="p">(</span><span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="s2">"dummy"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span> <span class="o">||</span> <span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"dummy"</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span><span class="p">)</span> - <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPCRYPT_NONE</span><span class="p">:</span> + <span class="n">case</span> <span class="n">PPCRYPT_DONE</span><span class="p">:</span> + <span class="k">break</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPCRYPT_PASS</span><span class="p">:</span> + <span class="k">if</span> <span class="p">(</span><span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="s2">"dummy"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span> <span class="o">||</span> <span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"dummy"</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span><span class="p">)</span> + <span class="k">break</span><span class="p">;</span> <span class="n">printf</span><span class="p">(</span><span class="s2">"sorry, password needed</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span> <span class="k">continue</span><span class="p">;</span> - <span class="n">case</span> <span class="n">PPCRYPT_FAIL</span><span class="p">:</span> - <span class="n">printf</span><span class="p">(</span><span class="s2">"sorry, encryption failed</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> - <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span> - <span class="k">continue</span><span class="p">;</span> + <span class="n">case</span> <span class="n">PPCRYPT_FAIL</span><span class="p">:</span> + <span class="n">printf</span><span class="p">(</span><span class="s2">"sorry, encryption failed</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> + <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span> + <span class="k">continue</span><span class="p">;</span> <span class="p">}</span> - <span class="n">filename</span> <span class="o">=</span> <span class="n">get_file_name</span><span class="p">(</span><span class="n">filepath</span><span class="p">);</span> - <span class="n">sprintf</span><span class="p">(</span><span class="n">outname</span><span class="p">,</span> <span class="n">OUTDIR</span> <span class="s2">"/</span><span class="si">%s</span><span class="s2">.out"</span><span class="p">,</span> <span class="n">filename</span><span class="p">);</span> + <span class="n">sprintf</span><span class="p">(</span><span class="n">outname</span><span class="p">,</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">.out"</span><span class="p">,</span> <span class="n">filepath</span><span class="p">);</span> <span class="n">fh</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="n">outname</span><span class="p">,</span> <span class="s2">"wb"</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="n">fh</span> <span class="o">==</span> <span class="n">NULL</span><span class="p">)</span> <span class="p">{</span> @@ -308,10 +334,10 @@ <span class="n">obj</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">;</span> <span class="n">obj</span> <span class="o">=</span> <span class="n">ppcontents_next_op</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">,</span> <span class="o">&</span><span class="n">op</span><span class="p">))</span> <span class="o">++</span><span class="n">operators</span><span class="p">;</span> - <span class="n">fprintf</span><span class="p">(</span><span class="n">fh</span><span class="p">,</span> <span class="s2">"</span><span class="si">%%%%</span><span class="s2"> OPERATORS count "</span> <span class="n">PPSIZEF</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">operators</span><span class="p">);</span> + <span class="n">fprintf</span><span class="p">(</span><span class="n">fh</span><span class="p">,</span> <span class="s2">"</span><span class="si">%%%%</span><span class="s2"> OPERATORS count </span><span class="si">%lu</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="p">(</span><span class="n">unsigned</span> <span class="n">long</span><span class="p">)</span><span class="n">operators</span><span class="p">);</span> <span class="n">ppstream_done</span><span class="p">(</span><span class="n">stream</span><span class="p">);</span> <span class="o">//</span><span class="n">obj</span> <span class="o">=</span> <span class="n">ppcontents_parse</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">stream</span><span class="p">,</span> <span class="o">&</span><span class="n">size</span><span class="p">);</span> - <span class="o">//</span><span class="n">fprintf</span><span class="p">(</span><span class="n">fh</span><span class="p">,</span> <span class="s2">"</span><span class="si">%%%%</span><span class="s2"> items count "</span> <span class="n">PPSIZEF</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span> + <span class="o">//</span><span class="n">fprintf</span><span class="p">(</span><span class="n">fh</span><span class="p">,</span> <span class="s2">"</span><span class="si">%%%%</span><span class="s2"> items count </span><span class="si">%lu</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="p">(</span><span class="n">unsigned</span> <span class="n">long</span><span class="p">)</span><span class="n">size</span><span class="p">);</span> <span class="n">fprintf</span><span class="p">(</span><span class="n">fh</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">);</span> <span class="p">}</span> <span class="n">ppcontext_done</span><span class="p">(</span><span class="n">context</span><span class="p">);</span> @@ -320,7 +346,7 @@ <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span> <span class="p">}</span> <span class="n">ppcontext_free</span><span class="p">(</span><span class="n">context</span><span class="p">);</span> - <span class="n">ppstream_free_buffers</span><span class="p">();</span> + <span class="n">ppstream_free_buffers</span><span class="p">();</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </pre></div> @@ -336,9 +362,9 @@ static int usage (const char *argv0) { - printf("pplib " pplib_version ", " pplib_author "\n"); - printf("usage: %s file1.pdf file2.pdf ...\n", argv0); - return 0; + printf("pplib " pplib_version ", " pplib_author "\n"); + printf("usage: %s file1.pdf file2.pdf ...\n", argv0); + return 0; } static void print_result_filter (ppstream *stream, int decode) @@ -347,45 +373,65 @@ static void print_result_filter (ppstream *stream, int decode) size_t i; ppstream_filter_info(stream, &info, decode); - printf("when %s: /Filter [", decode ? "uncompressed" : "compressed"); + printf(" when %s: /Filter [", decode ? "uncompressed" : "compressed"); for (i = 0; i < info.count; ++i) - printf(" /%s", ppstream_filter_name[info.filters[i]]); - printf(" ]"); - if (info.params != NULL) - { - printf(" /DecodeParms ["); - for (i = 0; i < info.count; ++i) - printf(" %s", info.params[i] != NULL ? "<<...>>" : "null"); - printf(" ]"); - } + printf(" /%s", ppstream_filter_name[info.filters[i]]); + printf(" ]"); + if (info.params != NULL) + { + printf(" /DecodeParms ["); + for (i = 0; i < info.count; ++i) + printf(" %s", info.params[i] != NULL ? "<<...>>" : "null"); + printf(" ]"); + } printf("\n"); } static void print_stream_info (ppref *ref, ppstream *stream) -{ - size_t length; - printf("object %lu %lu R\n", (unsigned long)ref->number, (unsigned long)ref->version); - if (stream->flags & PPSTREAM_FILTER) - printf("filtered "); - else - printf("plain "); - if (stream->flags & PPSTREAM_IMAGE) - printf("image "); - else - printf("stream "); - if (stream->flags & PPSTREAM_ENCRYPTED) - printf("encrypted "); - if (stream->flags & PPSTREAM_NOT_SUPPORTED) - printf("invalid "); - if (!ppdict_rget_uint(stream->dict, "Length", &length)) - length = 0; - assert(stream->length == length); - printf("length %lu (/Length %lu)\n", (unsigned long)stream->length, (unsigned long)length); - print_result_filter(stream, 0); - print_result_filter(stream, 1); - printf("\n"); +{ + size_t length; + printf("object %lu %lu R\n", (unsigned long)ref->number, (unsigned long)ref->version); + if (stream->flags & PPSTREAM_FILTER) + printf(" filtered "); + else + printf(" plain "); + if (stream->flags & PPSTREAM_IMAGE) + printf("image "); + else + printf("stream "); + if (stream->flags & PPSTREAM_ENCRYPTED) + printf("encrypted "); + if (stream->flags & PPSTREAM_NOT_SUPPORTED) + printf("invalid "); + if (!ppdict_rget_uint(stream->dict, "Length", &length)) + length = 0; + assert(stream->length == length); + printf("length %lu (/Length %lu)\n", (unsigned long)stream->length, (unsigned long)length); + print_result_filter(stream, 0); + print_result_filter(stream, 1); +} + +static void check_stream_chunks (ppstream *stream) +{ + size_t sum, size; + uint8_t *data; + const int decode[2] = {0, 1}; + int d; + + for (d = 0; d < 2; ++d) + { + for (sum = 0, data = ppstream_first(stream, &size, decode[d]); data != NULL; data = ppstream_next(stream, &size)) + sum += size; + ppstream_done(stream); + ppstream_all(stream, &size, decode[d]); + ppstream_done(stream); + assert(sum == size); + printf(" %s chunks size [%lu]\n", (decode[d] ? "decoded" : "raw"), (unsigned long)size); + } } +#define USE_BUFFERS_POOL 1 + int main (int argc, const char **argv) { const char *filepath; @@ -399,6 +445,8 @@ int main (int argc, const char **argv) if (argc < 2) return usage(argv[0]); + if (USE_BUFFERS_POOL) + ppstream_init_buffers(); for (a = 1; a < argc; ++a) { filepath = argv[a]; @@ -410,20 +458,23 @@ int main (int argc, const char **argv) continue; } printf("done.\n"); - for (xref = ppdoc_xref(pdf); xref != NULL; xref = ppxref_prev(xref)) - { - for (xi = 0, xsec = xref->sects; xi < xref->size; ++xi, ++xsec) - { - for (refnum = xsec->first, ref = xsec->refs; refnum <= xsec->last; ++refnum, ++ref) - { - if (ref->object.type != PPSTREAM) - continue; - print_stream_info(ref, ref->object.stream); - } - } - } + for (xref = ppdoc_xref(pdf); xref != NULL; xref = ppxref_prev(xref)) + { + for (xi = 0, xsec = xref->sects; xi < xref->size; ++xi, ++xsec) + { + for (refnum = xsec->first, ref = xsec->refs; refnum <= xsec->last; ++refnum, ++ref) + { + if (ref->object.type != PPSTREAM) + continue; + print_stream_info(ref, ref->object.stream); + check_stream_chunks(ref->object.stream); + } + } + } ppdoc_free(pdf); } + if (USE_BUFFERS_POOL) + ppstream_free_buffers(); return 0; } </pre></div> @@ -441,7 +492,7 @@ int main (int argc, const char **argv) <span class="c1">#include "ppconf.h"</span> -<span class="c1">#define pplib_version "v1.03"</span> +<span class="c1">#define pplib_version "v2.05 less toxic i hope"</span> <span class="c1">#define pplib_author "p.jackowski@gust.org.pl"</span> <span class="o">/*</span> <span class="n">types</span> <span class="o">*/</span> @@ -449,54 +500,41 @@ int main (int argc, const char **argv) <span class="n">typedef</span> <span class="n">int64_t</span> <span class="n">ppint</span><span class="p">;</span> <span class="n">typedef</span> <span class="n">size_t</span> <span class="n">ppuint</span><span class="p">;</span> <span class="o">//</span> <span class="n">machine</span> <span class="n">word</span> +<span class="n">typedef</span> <span class="n">char</span> <span class="n">ppbyte</span><span class="p">;</span> + <span class="n">typedef</span> <span class="n">double</span> <span class="n">ppnum</span><span class="p">;</span> -<span class="n">typedef</span> <span class="n">char</span> <span class="o">*</span> <span class="n">ppname</span><span class="p">;</span> -<span class="n">typedef</span> <span class="n">char</span> <span class="o">*</span> <span class="n">ppstring</span><span class="p">;</span> -<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span> +<span class="n">typedef</span> <span class="n">struct</span> <span class="n">ppname</span> <span class="n">ppname</span><span class="p">;</span> +<span class="n">typedef</span> <span class="n">struct</span> <span class="n">ppstring</span> <span class="n">ppstring</span><span class="p">;</span> + +<span class="n">struct</span> <span class="n">ppname</span> <span class="p">{</span> + <span class="n">ppbyte</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span> <span class="n">size_t</span> <span class="n">size</span><span class="p">;</span> + <span class="n">ppname</span> <span class="o">*</span><span class="n">alterego</span><span class="p">;</span> <span class="nb">int</span> <span class="n">flags</span><span class="p">;</span> -<span class="p">}</span> <span class="n">_ppname</span><span class="p">;</span> +<span class="p">};</span> -<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span> +<span class="n">struct</span> <span class="n">ppstring</span> <span class="p">{</span> + <span class="n">ppbyte</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span> <span class="n">size_t</span> <span class="n">size</span><span class="p">;</span> + <span class="n">ppstring</span> <span class="o">*</span><span class="n">alterego</span><span class="p">;</span> <span class="nb">int</span> <span class="n">flags</span><span class="p">;</span> -<span class="p">}</span> <span class="n">_ppstring</span><span class="p">;</span> +<span class="p">};</span> <span class="n">typedef</span> <span class="n">struct</span> <span class="n">ppobj</span> <span class="n">ppobj</span><span class="p">;</span> <span class="n">typedef</span> <span class="n">struct</span> <span class="n">ppref</span> <span class="n">ppref</span><span class="p">;</span> - -<span class="c1">#if ARM_COMPLIANT</span> -<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span> - <span class="n">ppobj</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span> - <span class="n">size_t</span> <span class="n">size</span><span class="p">;</span> - <span class="n">ppnum</span> <span class="n">PPARRAY_ALIGNMENT</span><span class="p">;</span> -<span class="p">}</span> <span class="n">pparray</span><span class="p">;</span> -<span class="c1">#else</span> <span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span> <span class="n">ppobj</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span> <span class="n">size_t</span> <span class="n">size</span><span class="p">;</span> <span class="p">}</span> <span class="n">pparray</span><span class="p">;</span> -<span class="c1">#endif</span> - -<span class="c1">#if ARM_COMPLIANT</span> <span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span> <span class="n">ppobj</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span> - <span class="n">ppname</span> <span class="o">*</span><span class="n">keys</span><span class="p">;</span> + <span class="n">ppname</span> <span class="o">**</span><span class="n">keys</span><span class="p">;</span> <span class="n">size_t</span> <span class="n">size</span><span class="p">;</span> - <span class="n">ppnum</span> <span class="n">PPDICT_ALIGNMENT</span><span class="p">;</span> <span class="p">}</span> <span class="n">ppdict</span><span class="p">;</span> -<span class="c1">#else</span> -<span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span> - <span class="n">ppobj</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span> - <span class="n">ppname</span> <span class="o">*</span><span class="n">keys</span><span class="p">;</span> - <span class="n">size_t</span> <span class="n">size</span><span class="p">;</span> -<span class="p">}</span> <span class="n">ppdict</span><span class="p">;</span> -<span class="c1">#endif</span> - <span class="n">typedef</span> <span class="n">enum</span> <span class="p">{</span> <span class="n">PPSTREAM_BASE16</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">PPSTREAM_BASE85</span><span class="p">,</span> @@ -523,12 +561,12 @@ int main (int argc, const char **argv) <span class="n">size_t</span> <span class="n">length</span><span class="p">;</span> <span class="n">ppstream_filter</span> <span class="nb">filter</span><span class="p">;</span> <span class="n">ppobj</span> <span class="o">*</span><span class="n">filespec</span><span class="p">;</span> - <span class="n">ppstring</span> <span class="n">cryptkey</span><span class="p">;</span> + <span class="n">ppstring</span> <span class="o">*</span><span class="n">cryptkey</span><span class="p">;</span> <span class="nb">int</span> <span class="n">flags</span><span class="p">;</span> <span class="p">}</span> <span class="n">ppstream</span><span class="p">;</span> <span class="n">PPDEF</span> <span class="n">extern</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">ppstream_filter_name</span><span class="p">[];</span> -<span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">ppstream_filter_type</span> <span class="p">(</span><span class="n">ppname</span> <span class="n">filtername</span><span class="p">,</span> <span class="n">ppstreamtp</span> <span class="o">*</span><span class="n">filtertype</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">ppstream_filter_type</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">filtername</span><span class="p">,</span> <span class="n">ppstreamtp</span> <span class="o">*</span><span class="n">filtertype</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">void</span> <span class="n">ppstream_filter_info</span> <span class="p">(</span><span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">ppstream_filter</span> <span class="o">*</span><span class="n">info</span><span class="p">,</span> <span class="nb">int</span> <span class="n">decode</span><span class="p">);</span> <span class="c1">#define PPSTREAM_FILTER (1<<0)</span> @@ -561,18 +599,18 @@ int main (int argc, const char **argv) <span class="n">PPDEF</span> <span class="n">extern</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">ppobj_kind</span><span class="p">[];</span> <span class="n">struct</span> <span class="n">ppobj</span> <span class="p">{</span> - <span class="n">ppobjtp</span> <span class="nb">type</span><span class="p">;</span> <span class="n">union</span> <span class="p">{</span> <span class="n">ppint</span> <span class="n">integer</span><span class="p">;</span> <span class="n">ppnum</span> <span class="n">number</span><span class="p">;</span> - <span class="n">ppname</span> <span class="n">name</span><span class="p">;</span> - <span class="n">ppstring</span> <span class="n">string</span><span class="p">;</span> + <span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span> + <span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">;</span> <span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">;</span> <span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">;</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">;</span> <span class="n">ppref</span> <span class="o">*</span><span class="n">ref</span><span class="p">;</span> <span class="n">void</span> <span class="o">*</span><span class="nb">any</span><span class="p">;</span> <span class="p">};</span> + <span class="n">ppobjtp</span> <span class="nb">type</span><span class="p">;</span> <span class="p">};</span> <span class="n">typedef</span> <span class="n">struct</span> <span class="n">ppxref</span> <span class="n">ppxref</span><span class="p">;</span> @@ -620,34 +658,27 @@ int main (int argc, const char **argv) <span class="o">/*</span> <span class="n">name</span> <span class="o">*/</span> -<span class="c1">#define ppname_is(name, s) (memcmp(name, s, sizeof("" s) - 1) == 0)</span> -<span class="c1">#define ppname_eq(name, n) (memcmp(name, s, ppname_size(name)) == 0)</span> - -<span class="c1">#if ARM_COMPLIANT</span> -<span class="c1">#define _ppname_ghost(name) (((const _ppname *)((void *)name)) - 1)</span> -<span class="c1">#else</span> -<span class="c1">#define _ppname_ghost(name) (((const _ppname *)(name)) - 1)</span> -<span class="c1">#endif</span> +<span class="c1">#define ppname_is(name, s) (memcmp((name)->data, s, sizeof("" s) - 1) == 0)</span> +<span class="c1">#define ppname_eq(name, n) (memcmp((name)->data, s, (name)->size) == 0)</span> -<span class="c1">#define ppname_size(name) (_ppname_ghost(name)->size)</span> -<span class="c1">#define ppname_exec(name) (_ppname_ghost(name)->flags & PPNAME_EXEC)</span> +<span class="c1">#define ppname_size(name) ((name)->size)</span> +<span class="c1">#define ppname_exec(name) ((name)->flags & PPNAME_EXEC)</span> +<span class="c1">#define ppname_data(name) ((name)->data)</span> <span class="c1">#define PPNAME_ENCODED (1 << 0)</span> <span class="c1">#define PPNAME_DECODED (1 << 1)</span> <span class="c1">#define PPNAME_EXEC (1 << 1)</span> -<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="n">ppname_decoded</span> <span class="p">(</span><span class="n">ppname</span> <span class="n">name</span><span class="p">);</span> -<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="n">ppname_encoded</span> <span class="p">(</span><span class="n">ppname</span> <span class="n">name</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="o">*</span> <span class="n">ppname_decoded</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="o">*</span> <span class="n">ppname_encoded</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> -<span class="o">/*</span> <span class="n">string</span> <span class="o">*/</span> +<span class="n">PPAPI</span> <span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppname_decoded_data</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppname_encoded_data</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> -<span class="c1">#if ARM_COMPLIANT</span> -<span class="c1">#define _ppstring_ghost(string) (((const _ppstring *)((void *)string)) - 1)</span> -<span class="c1">#else</span> -<span class="c1">#define _ppstring_ghost(string) (((const _ppstring *)(string)) - 1)</span> -<span class="c1">#endif</span> +<span class="o">/*</span> <span class="n">string</span> <span class="o">*/</span> -<span class="c1">#define ppstring_size(string) (_ppstring_ghost(string)->size)</span> +<span class="c1">#define ppstring_size(string) ((string)->size)</span> +<span class="c1">#define ppstring_data(string) ((string)->data)</span> <span class="c1">#define PPSTRING_ENCODED (1 << 0)</span> <span class="c1">#define PPSTRING_DECODED (1 << 1)</span> @@ -658,12 +689,15 @@ int main (int argc, const char **argv) <span class="c1">#define PPSTRING_UTF16BE (1 << 5)</span> <span class="c1">#define PPSTRING_UTF16LE (1 << 6)</span> -<span class="c1">#define ppstring_type(string) (_ppstring_ghost(string)->flags & (PPSTRING_BASE16|PPSTRING_BASE85))</span> -<span class="c1">#define ppstring_hex(string) (_ppstring_ghost(string)->flags & PPSTRING_BASE16)</span> -<span class="c1">#define ppstring_utf(string) (_ppstring_ghost(string)->flags & (PPSTRING_UTF16BE|PPSTRING_UTF16LE))</span> +<span class="c1">#define ppstring_type(string) ((string)->flags & (PPSTRING_BASE16|PPSTRING_BASE85))</span> +<span class="c1">#define ppstring_hex(string) ((string)->flags & PPSTRING_BASE16)</span> +<span class="c1">#define ppstring_utf(string) ((string)->flags & (PPSTRING_UTF16BE|PPSTRING_UTF16LE))</span> + +<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="o">*</span> <span class="n">ppstring_decoded</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="o">*</span> <span class="n">ppstring_encoded</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> -<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="n">ppstring_decoded</span> <span class="p">(</span><span class="n">ppstring</span> <span class="n">string</span><span class="p">);</span> -<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="n">ppstring_encoded</span> <span class="p">(</span><span class="n">ppstring</span> <span class="n">string</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppstring_decoded_data</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppstring_encoded_data</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> <span class="o">/*</span> <span class="n">array</span> <span class="o">*/</span> @@ -680,8 +714,8 @@ int main (int argc, const char **argv) <span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">pparray_get_int</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">ppint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">pparray_get_uint</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">ppuint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">pparray_get_num</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">ppnum</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> -<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="n">pparray_get_name</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> -<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="n">pparray_get_string</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="o">*</span> <span class="n">pparray_get_name</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="o">*</span> <span class="n">pparray_get_string</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">pparray</span> <span class="o">*</span> <span class="n">pparray_get_array</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">ppdict</span> <span class="o">*</span> <span class="n">pparray_get_dict</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="o">//</span><span class="n">PPAPI</span> <span class="n">ppstream</span> <span class="o">*</span> <span class="n">pparray_get_stream</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> @@ -692,8 +726,8 @@ int main (int argc, const char **argv) <span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">pparray_rget_int</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">ppint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">pparray_rget_uint</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">ppuint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">pparray_rget_num</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">,</span> <span class="n">ppnum</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> -<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="n">pparray_rget_name</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> -<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="n">pparray_rget_string</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="o">*</span> <span class="n">pparray_rget_name</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="o">*</span> <span class="n">pparray_rget_string</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">pparray</span> <span class="o">*</span> <span class="n">pparray_rget_array</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">ppdict</span> <span class="o">*</span> <span class="n">pparray_rget_dict</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">ppstream</span> <span class="o">*</span> <span class="n">pparray_rget_stream</span> <span class="p">(</span><span class="n">pparray</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">index</span><span class="p">);</span> @@ -710,8 +744,8 @@ int main (int argc, const char **argv) <span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">ppdict_get_int</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">ppdict_get_uint</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppuint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">ppdict_get_num</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppnum</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> -<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="n">ppdict_get_name</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> -<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="n">ppdict_get_string</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="o">*</span> <span class="n">ppdict_get_name</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="o">*</span> <span class="n">ppdict_get_string</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">pparray</span> <span class="o">*</span> <span class="n">ppdict_get_array</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppdict_get_dict</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> <span class="o">//</span><span class="n">PPAPI</span> <span class="n">ppstream</span> <span class="o">*</span> <span class="n">ppdict_get_stream</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> @@ -722,8 +756,8 @@ int main (int argc, const char **argv) <span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">ppdict_rget_int</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">ppdict_rget_uint</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppuint</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="nb">int</span> <span class="n">ppdict_rget_num</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="n">ppnum</span> <span class="o">*</span><span class="n">v</span><span class="p">);</span> -<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="n">ppdict_rget_name</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> -<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="n">ppdict_rget_string</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="o">*</span> <span class="n">ppdict_rget_name</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="o">*</span> <span class="n">ppdict_rget_string</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">pparray</span> <span class="o">*</span> <span class="n">ppdict_rget_array</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">ppdict</span> <span class="o">*</span> <span class="n">ppdict_rget_dict</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">ppstream</span> <span class="o">*</span> <span class="n">ppdict_rget_stream</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="nb">dict</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> @@ -761,6 +795,8 @@ int main (int argc, const char **argv) <span class="o">/*</span> <span class="n">doc</span> <span class="o">*/</span> <span class="n">PPAPI</span> <span class="n">ppdoc</span> <span class="o">*</span> <span class="n">ppdoc_load</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">filename</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppdoc</span> <span class="o">*</span> <span class="n">ppdoc_filehandle</span> <span class="p">(</span><span class="n">FILE</span> <span class="o">*</span><span class="n">file</span><span class="p">,</span> <span class="nb">int</span> <span class="n">closefile</span><span class="p">);</span> +<span class="c1">#define ppdoc_file(file) ppdoc_filehandle(file, 1)</span> <span class="n">PPAPI</span> <span class="n">ppdoc</span> <span class="o">*</span> <span class="n">ppdoc_mem</span> <span class="p">(</span><span class="n">const</span> <span class="n">void</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">size</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">void</span> <span class="n">ppdoc_free</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span> @@ -811,8 +847,8 @@ int main (int argc, const char **argv) <span class="o">/*</span> <span class="n">contents</span> <span class="n">parser</span> <span class="o">*/</span> -<span class="n">PPAPI</span> <span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppcontents_first_op</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">psize</span><span class="p">,</span> <span class="n">ppname</span> <span class="o">*</span><span class="n">pname</span><span class="p">);</span> -<span class="n">PPAPI</span> <span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppcontents_next_op</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">psize</span><span class="p">,</span> <span class="n">ppname</span> <span class="o">*</span><span class="n">pname</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppcontents_first_op</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">psize</span><span class="p">,</span> <span class="n">ppname</span> <span class="o">**</span><span class="n">pname</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppcontents_next_op</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">psize</span><span class="p">,</span> <span class="n">ppname</span> <span class="o">**</span><span class="n">pname</span><span class="p">);</span> <span class="n">PPAPI</span> <span class="n">ppobj</span> <span class="o">*</span> <span class="n">ppcontents_parse</span> <span class="p">(</span><span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">,</span> <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">psize</span><span class="p">);</span> <span class="o">/*</span> <span class="n">boxes</span> <span class="ow">and</span> <span class="n">transforms</span> <span class="o">*/</span> @@ -889,6 +925,43 @@ Revised streams handling, ppstream API extended</p> <h2>v1.04<a class="headerlink" href="#v1-04" title="Permalink to this headline">¶</a></h2> <p>Fixed TIFF predictor for ARM</p> </div> +<div class="section" id="v1-05"> +<h2>v1.05<a class="headerlink" href="#v1-05" title="Permalink to this headline">¶</a></h2> +<p>Attempt to fix parsing inline images crap</p> +</div> +<div class="section" id="v2-00"> +<h2>v2.00<a class="headerlink" href="#v2-00" title="Permalink to this headline">¶</a></h2> +<p>Deep rework on allocators. +Deep rework on strings and names.</p> +</div> +<div class="section" id="v2-01"> +<h2>v2.01<a class="headerlink" href="#v2-01" title="Permalink to this headline">¶</a></h2> +<p>Fixed invalid stream buffer handling; <code class="docutils literal notranslate"><span class="pre">iof_discard()</span></code> no longer reclaims the source (<code class="docutils literal notranslate"><span class="pre">filter->next</span></code>) filter. +Sanity alignment adjustments in <code class="docutils literal notranslate"><span class="pre">iof_heap</span></code>.</p> +</div> +<div class="section" id="v2-02"> +<h2>v2.02<a class="headerlink" href="#v2-02" title="Permalink to this headline">¶</a></h2> +<p>Fixed incorrect encoding of strings alterego with octal escaping, thanks Luigi. +On Hans request added <code class="docutils literal notranslate"><span class="pre">ppdoc_filehandle()</span></code> function and <code class="docutils literal notranslate"><span class="pre">ppdoc_file()</span></code> macro for loading ppdoc from <code class="docutils literal notranslate"><span class="pre">FILE</span> <span class="pre">*</span></code>.</p> +</div> +<div class="section" id="v2-03"> +<h2>v2.03<a class="headerlink" href="#v2-03" title="Permalink to this headline">¶</a></h2> +<p>Fixed alloc/free of <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> heap; <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> is now mallocated, no longer taken from its own heap. Again, thanks Luigi. +Fixed warnings about dereferencing type-puned pointers, and some others.</p> +</div> +<div class="section" id="v2-04"> +<h2>v2.04<a class="headerlink" href="#v2-04" title="Permalink to this headline">¶</a></h2> +<p>Byte lookups for names/strings loaders are now int8_t, as char might be signed. +ppdoc_first_page() / ppdoc_next_page() iterator now handles a case when /Kids array is empty. +Fixed generating keys for encrypted streams; ppstring_internal() returns the string of the proper size. +More stream tests in pptest3.c. +Some rework on md5 and sha2.</p> +</div> +<div class="section" id="v2-05"> +<h2>v2.05<a class="headerlink" href="#v2-05" title="Permalink to this headline">¶</a></h2> +<p>uint8_t instead of ppbyte in internals; ppbyte intent is “the most natural 8-bit integerâ€, so it is ‘char’, +but internally we almost always need uint8_t (char may be signed or not..)</p> +</div> </div> <div class="section" id="todo"> <h1>TODO<a class="headerlink" href="#todo" title="Permalink to this headline">¶</a></h1> @@ -910,14 +983,14 @@ Revised streams handling, ppstream API extended</p> <a href="genindex.html" title="General Index" >index</a></li> <li class="right" > - <a href="ppapi.html" title="pplib" + <a href="ppapi-1.x.html" title="pplib 1.x" >previous</a> |</li> <li class="nav-item nav-item-0"><a href="pplib.html">pplib 0.1 documentation</a> »</li> </ul> </div> <div class="footer" role="contentinfo"> - © Copyright 2018, p.jackowski@gust.org.pl. - Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.4. + © Copyright 2019, p.jackowski@gust.org.pl. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5. </div> </body> </html>
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/pplib.html b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/pplib.html index add2b726adf..3066c7ab6c8 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/pplib.html +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/pplib.html @@ -9,14 +9,16 @@ <title>pplib — pplib 0.1 documentation</title> <link rel="stylesheet" href="_static/bizstyle.css" type="text/css" /> <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> - <script type="text/javascript" src="_static/documentation_options.js"></script> + + <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> <script type="text/javascript" src="_static/jquery.js"></script> <script type="text/javascript" src="_static/underscore.js"></script> <script type="text/javascript" src="_static/doctools.js"></script> + <script type="text/javascript" src="_static/language_data.js"></script> <script type="text/javascript" src="_static/bizstyle.js"></script> <link rel="index" title="Index" href="genindex.html" /> <link rel="search" title="Search" href="search.html" /> - <link rel="next" title="pplib" href="ppapi.html" /> + <link rel="next" title="1.x vs 2.x" href="ppnew.html" /> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <!--[if lt IE 9]> <script type="text/javascript" src="_static/css3-mediaqueries.js"></script> @@ -29,7 +31,7 @@ <a href="genindex.html" title="General Index" accesskey="I">index</a></li> <li class="right" > - <a href="ppapi.html" title="pplib" + <a href="ppnew.html" title="1.x vs 2.x" accesskey="N">next</a> |</li> <li class="nav-item nav-item-0"><a href="#">pplib 0.1 documentation</a> »</li> </ul> @@ -37,8 +39,8 @@ <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> <div class="sphinxsidebarwrapper"> <h4>Next topic</h4> - <p class="topless"><a href="ppapi.html" - title="next chapter"><code class="docutils literal notranslate"><span class="pre">pplib</span></code></a></p> + <p class="topless"><a href="ppnew.html" + title="next chapter">1.x vs 2.x</a></p> <div role="note" aria-label="source link"> <h3>This Page</h3> <ul class="this-page-menu"> @@ -70,25 +72,52 @@ <h1>pplib<a class="headerlink" href="#pplib" title="Permalink to this headline">¶</a></h1> <div class="toctree-wrapper compound"> <ul> -<li class="toctree-l1"><a class="reference internal" href="ppapi.html"><code class="docutils literal notranslate"><span class="pre">pplib</span></code></a></li> -<li class="toctree-l1"><a class="reference internal" href="ppapi.html#c-api">C-API</a><ul> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#types">Types</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#object">Object</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#names">Names</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#string">String</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#array">Array</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#dict">Dict</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#stream">Stream</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#filters">Filters</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#ref">Ref</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#xref">XRef</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#pdf">PDF</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#encryption">Encryption</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#pages">Pages</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#contents">Contents</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#boxes">Boxes</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#transforms">Transforms</a></li> -<li class="toctree-l2"><a class="reference internal" href="ppapi.html#errors-handling">Errors handling</a></li> +<li class="toctree-l1"><a class="reference internal" href="ppnew.html">1.x vs 2.x</a><ul> +<li class="toctree-l2"><a class="reference internal" href="ppnew.html#allocation">Allocation</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppnew.html#strings-and-names">Strings And Names</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppnew.html#cleanups">Cleanups</a></li> +</ul> +</li> +<li class="toctree-l1"><a class="reference internal" href="ppapi-2.x.html"><code class="docutils literal notranslate"><span class="pre">pplib</span></code> 2.x</a></li> +<li class="toctree-l1"><a class="reference internal" href="ppapi-2.x.html#c-api">C-API</a><ul> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#types">Types</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#object">Object</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#names">Names</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#string">String</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#array">Array</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#dict">Dict</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#stream">Stream</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#filters">Filters</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#ref">Ref</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#xref">XRef</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#pdf">PDF</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#encryption">Encryption</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#pages">Pages</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#contents">Contents</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#boxes">Boxes</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#transforms">Transforms</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-2.x.html#errors-handling">Errors handling</a></li> +</ul> +</li> +<li class="toctree-l1"><a class="reference internal" href="ppapi-1.x.html"><code class="docutils literal notranslate"><span class="pre">pplib</span></code> 1.x</a></li> +<li class="toctree-l1"><a class="reference internal" href="ppapi-1.x.html#c-api">C-API</a><ul> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#types">Types</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#object">Object</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#names">Names</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#string">String</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#array">Array</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#dict">Dict</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#stream">Stream</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#filters">Filters</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#ref">Ref</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#xref">XRef</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#pdf">PDF</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#encryption">Encryption</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#pages">Pages</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#contents">Contents</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#boxes">Boxes</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#transforms">Transforms</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppapi-1.x.html#errors-handling">Errors handling</a></li> </ul> </li> <li class="toctree-l1"><a class="reference internal" href="ppcode.html">Examples</a><ul> @@ -107,6 +136,13 @@ <li class="toctree-l2"><a class="reference internal" href="ppcode.html#v1-02">v1.02</a></li> <li class="toctree-l2"><a class="reference internal" href="ppcode.html#v1-03">v1.03</a></li> <li class="toctree-l2"><a class="reference internal" href="ppcode.html#v1-04">v1.04</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppcode.html#v1-05">v1.05</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppcode.html#v2-00">v2.00</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppcode.html#v2-01">v2.01</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppcode.html#v2-02">v2.02</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppcode.html#v2-03">v2.03</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppcode.html#v2-04">v2.04</a></li> +<li class="toctree-l2"><a class="reference internal" href="ppcode.html#v2-05">v2.05</a></li> </ul> </li> <li class="toctree-l1"><a class="reference internal" href="ppcode.html#todo">TODO</a></li> @@ -127,14 +163,14 @@ <a href="genindex.html" title="General Index" >index</a></li> <li class="right" > - <a href="ppapi.html" title="pplib" + <a href="ppnew.html" title="1.x vs 2.x" >next</a> |</li> <li class="nav-item nav-item-0"><a href="#">pplib 0.1 documentation</a> »</li> </ul> </div> <div class="footer" role="contentinfo"> - © Copyright 2018, p.jackowski@gust.org.pl. - Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.4. + © Copyright 2019, p.jackowski@gust.org.pl. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5. </div> </body> </html>
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppnew.html b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppnew.html new file mode 100644 index 00000000000..734d81da1f3 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/ppnew.html @@ -0,0 +1,209 @@ + + +<!doctype html> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>1.x vs 2.x — pplib 0.1 documentation</title> + <link rel="stylesheet" href="_static/bizstyle.css" type="text/css" /> + <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> + + <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> + <script type="text/javascript" src="_static/jquery.js"></script> + <script type="text/javascript" src="_static/underscore.js"></script> + <script type="text/javascript" src="_static/doctools.js"></script> + <script type="text/javascript" src="_static/language_data.js"></script> + <script type="text/javascript" src="_static/bizstyle.js"></script> + <link rel="index" title="Index" href="genindex.html" /> + <link rel="search" title="Search" href="search.html" /> + <link rel="next" title="pplib 2.x" href="ppapi-2.x.html" /> + <link rel="prev" title="pplib" href="pplib.html" /> + <meta name="viewport" content="width=device-width,initial-scale=1.0"> + <!--[if lt IE 9]> + <script type="text/javascript" src="_static/css3-mediaqueries.js"></script> + <![endif]--> + </head><body> + <div class="related" role="navigation" aria-label="related navigation"> + <h3>Navigation</h3> + <ul> + <li class="right" style="margin-right: 10px"> + <a href="genindex.html" title="General Index" + accesskey="I">index</a></li> + <li class="right" > + <a href="ppapi-2.x.html" title="pplib 2.x" + accesskey="N">next</a> |</li> + <li class="right" > + <a href="pplib.html" title="pplib" + accesskey="P">previous</a> |</li> + <li class="nav-item nav-item-0"><a href="pplib.html">pplib 0.1 documentation</a> »</li> + </ul> + </div> + <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> + <div class="sphinxsidebarwrapper"> + <h3><a href="pplib.html">Table of Contents</a></h3> + <ul> +<li><a class="reference internal" href="#">1.x vs 2.x</a><ul> +<li><a class="reference internal" href="#allocation">Allocation</a></li> +<li><a class="reference internal" href="#strings-and-names">Strings And Names</a></li> +<li><a class="reference internal" href="#cleanups">Cleanups</a></li> +</ul> +</li> +</ul> + + <h4>Previous topic</h4> + <p class="topless"><a href="pplib.html" + title="previous chapter">pplib</a></p> + <h4>Next topic</h4> + <p class="topless"><a href="ppapi-2.x.html" + title="next chapter"><code class="docutils literal notranslate"><span class="pre">pplib</span></code> 2.x</a></p> + <div role="note" aria-label="source link"> + <h3>This Page</h3> + <ul class="this-page-menu"> + <li><a href="_sources/ppnew.rst.txt" + rel="nofollow">Show Source</a></li> + </ul> + </div> +<div id="searchbox" style="display: none" role="search"> + <h3>Quick search</h3> + <div class="searchformwrapper"> + <form class="search" action="search.html" method="get"> + <input type="text" name="q" /> + <input type="submit" value="Go" /> + <input type="hidden" name="check_keywords" value="yes" /> + <input type="hidden" name="area" value="default" /> + </form> + </div> +</div> +<script type="text/javascript">$('#searchbox').show(0);</script> + </div> + </div> + + <div class="document"> + <div class="documentwrapper"> + <div class="bodywrapper"> + <div class="body" role="main"> + + <div class="section" id="x-vs-2-x"> +<h1>1.x vs 2.x<a class="headerlink" href="#x-vs-2-x" title="Permalink to this headline">¶</a></h1> +<div class="section" id="allocation"> +<h2>Allocation<a class="headerlink" href="#allocation" title="Permalink to this headline">¶</a></h2> +<p>Allocation mechanisms has been revised. All objects are still allocated from a private storage (called heap), +but now the heap serves properly aligned memory chunks. Implementation of the heap is (hopefully) platform +independent, so all <code class="docutils literal notranslate"><span class="pre">ARM_COMPLIANT</span></code> checks has been removed. Some details work differently on 32/64-bit +machines, this distinction seems inevitable. Allocation related code has been moved to <code class="docutils literal notranslate"><span class="pre">util/utilmem*.c</span></code> files.</p> +<p>[There are actually 3 different allocators - <strong>heap</strong>, <strong>stock</strong>, and <strong>pool</strong> - each of which has 4 variants +for 1, 2, 4 and 8 bytes alignment. So far <code class="docutils literal notranslate"><span class="pre">pplib</span></code> uses only the <strong>heap</strong>, but I want to have this part +in a single place for a while. More notes about allocators in <code class="docutils literal notranslate"><span class="pre">utilmemallc.h</span></code>.]</p> +<p><code class="docutils literal notranslate"><span class="pre">pplib</span></code> uses two heaps:</p> +<ul class="simple"> +<li>bytes heap - providing 2-bytes aligned memory chunks for byte data</li> +<li>structures heap - providing 8-bytes aligned chunks for all structures</li> +</ul> +<p>2-bytes alignment of byte data is caused by implementation details / limits, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> doesn’t make a use of it +(could be unaligned as well). All the structures are stored in 8-bytes aligned chunks on both 32 and 64-bit machines +(in some structures we use <code class="docutils literal notranslate"><span class="pre">double</span></code> and <code class="docutils literal notranslate"><span class="pre">int64_t</span></code>, which generally needs 8-bytes).</p> +</div> +<div class="section" id="strings-and-names"> +<h2>Strings And Names<a class="headerlink" href="#strings-and-names" title="Permalink to this headline">¶</a></h2> +<p>So far, both <code class="docutils literal notranslate"><span class="pre">ppname</span></code> and <code class="docutils literal notranslate"><span class="pre">ppstring</span></code> were aliases to <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">*</span></code> with an extra structure hidden just below +the data address. The idea was to make a string or name usable whenever chars array can, at the cost of some +pointers trickery. Both names and strings keep an information about pdf-encoded data, as well as plain bytes data. +I implemented this feature once <code class="docutils literal notranslate"><span class="pre">pplib</span> <span class="pre">1.0</span></code> was almost done, and to avoid a revolution, I made that with yet +another trick. This all was dirty and caused lots of alignment issues.</p> +<p>Now <code class="docutils literal notranslate"><span class="pre">ppstring</span></code> and <code class="docutils literal notranslate"><span class="pre">ppname</span></code> are <strong>structures</strong>, keeping data and size members, pretty much like <code class="docutils literal notranslate"><span class="pre">pparray</span></code>:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">struct</span> <span class="n">ppname</span> <span class="p">{</span> + <span class="n">ppbyte</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span> + <span class="n">size_t</span> <span class="n">size</span><span class="p">;</span> + <span class="n">ppname</span> <span class="o">*</span><span class="n">alterego</span><span class="p">;</span> + <span class="nb">int</span> <span class="n">flags</span><span class="p">;</span> +<span class="p">};</span> + +<span class="n">struct</span> <span class="n">ppstring</span> <span class="p">{</span> + <span class="n">ppbyte</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span> + <span class="n">size_t</span> <span class="n">size</span><span class="p">;</span> + <span class="n">ppstring</span> <span class="o">*</span><span class="n">alterego</span><span class="p">;</span> + <span class="nb">int</span> <span class="n">flags</span><span class="p">;</span> +<span class="p">};</span> +</pre></div> +</div> +<p>Data member is a pointer to (2-bytes aligned) bytes array – <code class="docutils literal notranslate"><span class="pre">ppbyte</span> <span class="pre">*</span></code>. <code class="docutils literal notranslate"><span class="pre">ppbyte</span></code> is an alias to <code class="docutils literal notranslate"><span class="pre">char</span></code>. +<code class="docutils literal notranslate"><span class="pre">pplib</span></code> makes no assumptions about <code class="docutils literal notranslate"><span class="pre">ppbyte</span></code> signedness. [I’d prefer to have <code class="docutils literal notranslate"><span class="pre">uint8_t</span></code>, but better +keep that in sync with <code class="docutils literal notranslate"><span class="pre">ppdict_get_*</span></code> suite, which accepts <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">*</span></code>. Using <code class="docutils literal notranslate"><span class="pre">"string</span> <span class="pre">literals"</span></code> +with <code class="docutils literal notranslate"><span class="pre">ppdict_get</span></code> function is the most common case, I guess.]</p> +<p><code class="docutils literal notranslate"><span class="pre">ppname_size()</span></code> and <code class="docutils literal notranslate"><span class="pre">ppstring_size()</span> <span class="pre">``</span> <span class="pre">now</span> <span class="pre">have</span> +<span class="pre">trivial</span> <span class="pre">``ppname_data()</span></code> and <code class="docutils literal notranslate"><span class="pre">ppstring_data()</span></code> counterparts:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">#define ppname_size(name) ((name)->size)</span> +<span class="c1">#define ppname_data(name) ((name)->data)</span> + +<span class="c1">#define ppstring_size(string) ((string)->size)</span> +<span class="c1">#define ppstring_data(string) ((string)->data)</span> +</pre></div> +</div> +<p>Switching between encoded / decoded variants is made via explicit <code class="docutils literal notranslate"><span class="pre">alterego</span></code> member. If encoded and decoded forms +are identical, then <code class="docutils literal notranslate"><span class="pre">self->alfterego</span> <span class="pre">==</span> <span class="pre">self</span></code> (never NULL). Helper functions for that:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PPAPI</span> <span class="n">ppname</span> <span class="o">*</span> <span class="n">ppname_decoded</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppname</span> <span class="o">*</span> <span class="n">ppname_encoded</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> + +<span class="n">PPAPI</span> <span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppname_decoded_data</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppname_encoded_data</span> <span class="p">(</span><span class="n">ppname</span> <span class="o">*</span><span class="n">name</span><span class="p">);</span> + +<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="o">*</span> <span class="n">ppstring_decoded</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppstring</span> <span class="o">*</span> <span class="n">ppstring_encoded</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> + +<span class="n">PPAPI</span> <span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppstring_decoded_data</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> +<span class="n">PPAPI</span> <span class="n">ppbyte</span> <span class="o">*</span> <span class="n">ppstring_encoded_data</span> <span class="p">(</span><span class="n">ppstring</span> <span class="o">*</span><span class="n">string</span><span class="p">);</span> +</pre></div> +</div> +<p>Since <code class="docutils literal notranslate"><span class="pre">ppname</span></code> and <code class="docutils literal notranslate"><span class="pre">ppstring</span></code> are now structures, all API functions returning name/string or taking name/string +as an argument, now take <strong>a pointer to name/string</strong>. Watch out for <code class="docutils literal notranslate"><span class="pre">ppdict_get_*</span></code> functions suite. They still accept +<code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*</span></code> key as an argument, but <code class="docutils literal notranslate"><span class="pre">ppname</span></code> type can no longer be used there:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppname</span> <span class="n">key</span><span class="p">;</span> +<span class="n">ppdict_get_something</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">key</span><span class="p">);</span> <span class="o">//</span> <span class="n">wrong</span> +<span class="n">ppdict_get_something</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">key</span><span class="o">.</span><span class="n">data</span><span class="p">);</span> <span class="o">//</span> <span class="n">ok</span> + +<span class="n">ppname</span> <span class="o">*</span><span class="n">pkey</span><span class="p">;</span> +<span class="n">ppdict_get_something</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="p">)</span><span class="n">pkey</span><span class="p">);</span> <span class="o">//</span> <span class="n">wrong</span> +<span class="n">ppdict_get_something</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">pkey</span><span class="o">-></span><span class="n">data</span><span class="p">);</span> <span class="o">//</span> <span class="n">ok</span> +</pre></div> +</div> +<p>Consequently, functions / macros that used pointer to <code class="docutils literal notranslate"><span class="pre">ppname</span></code> (<code class="docutils literal notranslate"><span class="pre">ppdict_first()</span></code> / <code class="docutils literal notranslate"><span class="pre">ppdict_next()</span></code>), +now needs <code class="docutils literal notranslate"><span class="pre">ppname</span> <span class="pre">**pname</span></code>.</p> +</div> +<div class="section" id="cleanups"> +<h2>Cleanups<a class="headerlink" href="#cleanups" title="Permalink to this headline">¶</a></h2> +<p>Some of unused utils were removed. There is still some code in utils part that is not used by the library, +but I need this tollbox in many other places and don’t want to maintain two versions.</p> +<p>Some unification in integer types; <code class="docutils literal notranslate"><span class="pre">size_t</span></code> seems to be the best choice for and integer representing machine +word (<code class="docutils literal notranslate"><span class="pre">unsigned</span> <span class="pre">long</span></code> is not long enough on windows), less utils dependencies, less compiler warnings.</p> +</div> +</div> + + + </div> + </div> + </div> + <div class="clearer"></div> + </div> + <div class="related" role="navigation" aria-label="related navigation"> + <h3>Navigation</h3> + <ul> + <li class="right" style="margin-right: 10px"> + <a href="genindex.html" title="General Index" + >index</a></li> + <li class="right" > + <a href="ppapi-2.x.html" title="pplib 2.x" + >next</a> |</li> + <li class="right" > + <a href="pplib.html" title="pplib" + >previous</a> |</li> + <li class="nav-item nav-item-0"><a href="pplib.html">pplib 0.1 documentation</a> »</li> + </ul> + </div> + <div class="footer" role="contentinfo"> + © Copyright 2019, p.jackowski@gust.org.pl. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5. + </div> + </body> +</html>
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/search.html b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/search.html index b6a1fcfaee0..1f1c6ce65f5 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/search.html +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/search.html @@ -9,12 +9,15 @@ <title>Search — pplib 0.1 documentation</title> <link rel="stylesheet" href="_static/bizstyle.css" type="text/css" /> <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> - <script type="text/javascript" src="_static/documentation_options.js"></script> + + + <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> <script type="text/javascript" src="_static/jquery.js"></script> <script type="text/javascript" src="_static/underscore.js"></script> <script type="text/javascript" src="_static/doctools.js"></script> - <script type="text/javascript" src="_static/searchtools.js"></script> + <script type="text/javascript" src="_static/language_data.js"></script> <script type="text/javascript" src="_static/bizstyle.js"></script> + <script type="text/javascript" src="_static/searchtools.js"></script> <link rel="index" title="Index" href="genindex.html" /> <link rel="search" title="Search" href="#" /> <script type="text/javascript"> @@ -87,8 +90,8 @@ </ul> </div> <div class="footer" role="contentinfo"> - © Copyright 2018, p.jackowski@gust.org.pl. - Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.4. + © Copyright 2019, p.jackowski@gust.org.pl. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5. </div> </body> </html>
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/searchindex.js b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/searchindex.js new file mode 100644 index 00000000000..b59ee11455a --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/_build/html/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["ppapi-1.x","ppapi-2.x","ppcode","pplib","ppnew"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,sphinx:54},filenames:["ppapi-1.x.rst","ppapi-2.x.rst","ppcode.rst","pplib.rst","ppnew.rst"],objects:{},objnames:{},objtypes:{},terms:{"1mb":[0,1],"2fkb":2,"2fmb":2,"64kb":[0,1],"boolean":[0,1],"break":[0,1,2],"byte":[0,1,2,4],"case":[0,1,2,4],"char":[0,1,2,4],"const":[0,1,2,4],"default":[0,1,2],"enum":[0,1,2],"final":[0,1],"function":[0,1,2,4],"int":[0,1,2,4],"long":[0,1,2,4],"new":[0,1],"null":[0,1,2,4],"return":[0,1,2,4],"short":[0,1],"static":2,"switch":[0,1,2,4],"void":[0,1,2],"while":[0,1,4],And:[0,1,3],But:[0,1],For:[0,1],NOT:2,One:[0,1],Such:[0,1],The:[0,1,4],Then:[0,1],There:[0,1,4],Use:[0,1],Using:4,about:[0,1,2,4],abov:[0,1],absolutelli:[0,1],accept:[0,1,4],access:[0,1,2],accessor:[0,1],accord:[0,1],acrobat:[0,1,2],actual:[0,1,4],added:2,addit:[0,1],address:4,adjust:2,after:[0,1,2],again:[0,1,2],ahead:[0,1],alfterego:4,alia:[0,1,4],alias:[1,4],alien:[0,1,2],align:[2,4],aliv:[0,1],all:[0,1,4],alloc:[0,1,2,3],allow:[0,1],almost:[2,4],alreadi:[0,1],also:[0,1],alter:[0,1],alterego:[1,2,4],alwai:[0,1,2],among:[0,1],ani:[0,1,2],annoi:[0,1],anoth:[0,1,4],anyhow:[0,1],anymor:[0,1],anyth:[0,1],api:[2,3,4],app:0,appear:[0,1],appli:[0,1],applic:[0,1],approach:[0,1],approx:[0,1],arbitrari:[0,1],aren:[0,1],argc:2,argument:[0,1,4],argv0:2,argv:2,arm:2,arm_compli:4,arrai:[2,3,4],artbox:2,ascii85decod:[0,1],ascii:[0,1],asciihexdecod:[0,1],ask:[0,1],assert:2,associ:[0,1],assum:[0,1],assumpt:4,attempt:2,auxilari:[0,1],avail:[0,1],avoid:[0,1,4],awar:[0,1],base16:[0,1],base85:[0,1],basic:[0,1],bbox:[0,1],becaus:[0,1],been:[0,1,4],befor:[0,1,2],beings:[0,1],belong:[0,1],below:[0,1,4],besid:[0,1],best:4,better:[0,1,4],between:[0,1,4],beyond:[0,1],binari:[0,1],bit:[0,1,2,4],bleedbox:2,bodi:[0,1],boject:[0,1],bom:[0,1],both:[0,1,4],bother:[0,1],bound:[0,1],box:[2,3],box_info:2,buffer:[0,1,2],bug:[0,1],build:0,bunch:[0,1],call:[0,1,4],callback:[0,1],can:[0,1,2,4],care:[0,1],cast:[0,1],catalog:[0,1],caus:4,ccitt:[0,1],ccittfaxdecod:[0,1],chang:3,charact:[0,1,2],check:[0,1,4],check_stream_chunk:2,choic:4,chunk:[0,1,2,4],cipher:[0,1],cleanup:3,clear:0,close:[0,1],closefil:[1,2],code:[0,1,4],coercion:[0,1],come:[0,1],common:[0,1,4],compar:[0,1],comparison:[0,1],compil:4,complet:[0,1],completelli:[0,1],compound:[0,1],compress:[0,1,2],conceptu:[0,1],condit:[0,1],confus:[0,1],consequ:4,consid:0,constant:[0,1],construct:[0,1],contain:[0,1],content:[2,3],context:[0,1,2],continu:2,conveni:[0,1],convert:[0,1],copi:[0,1,2],correspond:[0,1],cost:[0,1,4],could:[0,1,4],count:[0,1,2],counterpart:[0,1,4],covert:[0,1],crap:2,creat:[0,1,2],creator:2,cropbox:2,cross:[0,1],crypt:[0,1,2],crypt_info:2,cryptkei:2,cstr:0,cstring:0,current:[0,1],custom:[0,1],data1:[0,1],data2:[0,1],data3:[0,1],data:[0,1,2,4],dct:[0,1],dctdecod:[0,1],deal:[0,1],declar:[0,1],decod:[0,1,2,4],decodeparm:[0,1,2],decompress:[0,1,2],decrypt:[0,1],dedic:[0,1],dedict:[0,1],deep:2,defin:[0,1,2,4],delim:[0,1],demand:[0,1],depend:[0,1,4],derefer:[0,1],dereferenc:2,describ:[0,1],descript:[0,1],design:[0,1],destroi:[0,1],detail:4,detect:[0,1],determin:[0,1],dict:[2,3,4],differ:[0,1,4],digit:[0,1,2],direct:[0,1],directli:[0,1],dirti:4,distinct:4,distinguish:[0,1],distingush:[0,1],doc:[1,2],document:[0,1],doe:[0,1],doesn:[0,1,4],don:[0,1,4],done:[0,1,2,4],doubl:[0,1,2,4],due:[0,1],dummi:[0,1,2],each:[0,1,4],eat:[0,1],effect:[0,1,2],ego:[0,1],egzot:2,element:[0,1],elementari:[0,1],els:2,empti:[0,1,2],encod:[0,1,2,4],encrypt:[2,3],end:[0,1],endif:2,enough:[0,1,4],ensur:[0,1],entir:[0,1],entri:[0,1],equiv:[0,1],error:3,escap:[0,1,2],even:[0,1],everi:[0,1],exactli:[0,1],exampl:[0,1,3],except:[0,1],execut:[0,1],expect:[0,1],explain:[0,1],explicit:[0,1,4],expos:[0,1],extend:[0,2],extens:0,extern:2,extra:[0,1,4],fail:[0,1,2],failur:[0,1],far:[0,1,4],fast:0,fault:0,fclose:[1,2],featur:[0,1,4],fetch:[0,1],field:[0,1,2],file1:2,file2:2,file:[0,1,2,4],filenam:[0,1,2],filepath:2,files:2,filespec:2,fill:[0,1,2],filter:[2,3],filternam:[0,1,2],filtertyp:[0,1,2],find:[0,1],finder:2,first:[0,1,2],fix:2,flag:[0,1,2,4],flate:[0,1],flatedecod:[0,1],fly:[0,1],folk:2,follow:[0,1],fopen:2,forbidden:0,form:[0,1,2,4],found:[0,1],fprintf:[0,1,2],free:[0,1,2],freed:[0,1],from:[0,1,2,4],futur:[0,1],fwrite:2,gener:[2,4],genuin:[0,1],get:[0,1],get_file_nam:2,getter:[0,1],give:[0,1],given:[0,1],gobbl:2,goe:[0,1],going:[0,1],grant:[0,1],grow:[0,1],guess:[0,1,4],gust:2,han:2,handl:[2,3],handler:[0,1],happen:[0,1,2],has:[0,1,4],hash:[0,1],have:[0,1,4],haven:[0,1],header:[0,1],heap:[0,1,2,4],helper:[0,1,4],here:[0,1],hex:[0,1],hidden:4,hide:0,hope:2,hopefulli:4,host:[0,1],how:[0,1],howev:0,hundr:0,idea:4,ident:[0,1,4],identifi:[0,1],iff:[0,1],ifndef:2,imag:[0,1,2],imagedict:[0,1],implement:[0,1,4],includ:[0,1,2],incomplet:[0,1],incorrect:2,increment:[0,1,2],independ:[0,1,4],index:[0,1,2],indic:[0,1],indirect:[0,1],inevit:4,info:[0,1,2],inform:[0,1,4],initi:[0,1],inlin:[0,1,2],input:2,instead:[0,1,2],insuffici:[0,1],int64_t:[0,1,2,4],int8_t:2,integ:[0,1,2,4],integr:2,intend:[0,1],intent:[0,1,2],interfac:[0,1],intern:[0,1,2],introduc:[0,1],invalid:[0,1,2],iof_copy_file_data:2,iof_discard:2,iof_heap:2,issu:4,item:[0,1,2],iter:[0,1,2],its:[0,1,2],itself:[0,1],jackowski:2,jbig2:[0,1],jbig2decod:[0,1],jbig:[0,1],jpeg:[0,1],jpegsiz:[0,1],jpegstream:[0,1],jpx:[0,1],jpxdecod:[0,1],jump:[0,1],just:[0,1,4],keep:[0,1,4],kei:[0,1,2,4],kep:[0,1],kept:[0,1],keyval:[0,1],keyword:2,kid:2,kind:[0,1],know:[0,1],known:[0,1],larg:[0,1],last:[0,1,2],later:[0,1],lead:[0,1],length:[0,1,2],less:[0,1,2,4],letter:[0,1],librari:[0,1,4],like:[0,1,4],limit:4,linear:[0,1],list:[0,1],liter:[0,1,4],load:[0,1,2],loader:[0,1,2],log:[0,1],log_callback:2,logger:[0,1,2],longer:[0,1,2,4],look:[0,1],lookup:[0,2],loop:[0,1],lot:4,luatex:2,luigi:2,lzw:[0,1],lzwdecod:[0,1],machin:[0,1,2,4],macro:[0,1,2,4],made:4,magic:[0,1],mai:[0,1,2],main:[0,1,2],maintain:4,major:[0,1],make:[0,1,4],malloc:[0,1,2],mani:4,map:[0,1],mark:[0,1],match:[0,1],matrix:[0,1,2],matter:[0,1],md5:2,mean:[0,1],mechan:4,mediabox:[0,1,2],mem:2,member:[0,1,4],memcmp:[0,1,2],memori:[0,1,2,4],memus:2,memwast:2,mention:[0,1],messag:[0,1,2],might:[0,1,2],mind:[0,1],minor:[0,1,2],moment:[0,1],more:[0,1,2,4],most:[0,1,2,4],move:4,much:4,must:[0,1],name:[2,3],natur:2,necessari:[0,1],need:[0,1,2,4],never:4,newest:[0,1],next:[0,1,2],node:[0,1],non:[0,1],none:2,nonempti:2,nooop:[0,1,2],normal:[0,1],note:[0,1,2,4],noth:[0,1],now:[0,1,2,4],number:[0,1,2],numer:[0,1],obj:[0,1,2],object:[2,3,4],obligatori:[0,1],obscur:[0,1],octal:2,offset:[0,1,2],often:[0,1],older:[0,1],omit:[0,1],onc:[0,1,4],one:[0,1],onli:[0,1,2,4],open:[0,1,2],openbsd:[],oper:[0,1,2],operand:[0,1],operato:[0,1],oprat:[0,1],option:[0,1],org:2,origin:[0,1],other:[0,1,2,4],otherwis:[0,1],out:[0,1,2,4],outnam:2,output:[0,1],over:[0,1],own:[0,1,2],owner:[0,1],ownerpass:[0,1,2],ownerpasslength:[0,1,2],page:[2,3],pagecount:2,pagedict:[0,1,2],pageno:[0,1,2],pageref:2,paid:1,pair:[0,1],parallel:[0,1],param:[0,1,2],paramet:[0,1],parent:[0,1],pars:[0,1,2],parser:[0,1,2],part:[0,1,4],password:[0,1,2],path:2,pcontext:[0,1],pdf:[2,3,4],perfectli:0,perform:[0,1],permiss:[0,1,2],piec:[0,1],pkei:[0,1,2,4],place:4,plain:[0,1,2,4],platform:4,plu:2,pname:[0,1,2,4],point:[0,1],pointer:[0,1,2,4],pool:[0,1,4],portabl:2,possibl:[0,1],postscript:[0,1,2],pp_api_h:2,ppapi:[0,1,3,4],pparrai:[0,1,2,4],pparray_at:[0,1,2],pparray_first:[0,1,2],pparray_get:[0,1,2],pparray_get_:[0,1],pparray_get_arrai:[0,1,2],pparray_get_bool:[0,1,2],pparray_get_dict:[0,1,2],pparray_get_int:[0,1,2],pparray_get_nam:[0,1,2],pparray_get_num:[0,1,2],pparray_get_obj:[0,1,2],pparray_get_ref:[0,1,2],pparray_get_str:[0,1,2],pparray_get_stream:[0,1,2],pparray_get_uint:[0,1,2],pparray_next:[0,1,2],pparray_rget_:[0,1],pparray_rget_arrai:2,pparray_rget_bool:2,pparray_rget_dict:2,pparray_rget_int:2,pparray_rget_nam:2,pparray_rget_num:2,pparray_rget_obj:2,pparray_rget_ref:2,pparray_rget_str:2,pparray_rget_stream:[0,1,2],pparray_rget_uint:2,pparray_s:[0,1,2],pparray_to_matrix:[0,1,2],pparray_to_rect:[0,1,2],ppbool:[0,1,2],ppbyte:[1,2,4],ppconf:2,ppcontents_first:[0,1,2],ppcontents_first_op:[0,1,2],ppcontents_next:[0,1,2],ppcontents_next_op:[0,1,2],ppcontents_pars:[0,1,2],ppcontext:[0,1,2],ppcontext_don:[0,1,2],ppcontext_fre:[0,1,2],ppcontext_new:[0,1,2],ppcrypt_don:[0,1,2],ppcrypt_fail:[0,1,2],ppcrypt_non:[0,1,2],ppcrypt_pass:[0,1,2],ppcrypt_statu:[0,1,2],ppdef:2,ppdic_rget_dict:[0,1],ppdict:[0,1,2],ppdict_at:[0,1,2],ppdict_first:[0,1,2,4],ppdict_get:4,ppdict_get_:[0,1,4],ppdict_get_arrai:[0,1,2],ppdict_get_bool:[0,1,2],ppdict_get_box:[0,1,2],ppdict_get_dict:[0,1,2],ppdict_get_int:[0,1,2],ppdict_get_matrix:[0,1,2],ppdict_get_nam:[0,1,2],ppdict_get_num:[0,1,2],ppdict_get_obj:[0,1,2],ppdict_get_rect:[0,1,2],ppdict_get_ref:[0,1,2],ppdict_get_someth:4,ppdict_get_str:[0,1,2],ppdict_get_stream:[0,1,2],ppdict_get_uint:[0,1,2],ppdict_kei:[0,1,2],ppdict_next:[0,1,2,4],ppdict_rget_:[0,1],ppdict_rget_arrai:2,ppdict_rget_bool:2,ppdict_rget_dict:[0,1,2],ppdict_rget_int:2,ppdict_rget_nam:2,ppdict_rget_num:2,ppdict_rget_obj:2,ppdict_rget_ref:2,ppdict_rget_str:2,ppdict_rget_stream:[0,1,2],ppdict_rget_uint:2,ppdict_siz:[0,1,2],ppdoc:[0,1,2],ppdoc_allow_annot:[0,1,2],ppdoc_allow_assembl:[0,1,2],ppdoc_allow_copi:[0,1,2],ppdoc_allow_extract:[0,1,2],ppdoc_allow_modifi:[0,1,2],ppdoc_allow_print:[0,1,2],ppdoc_allow_print_hir:[0,1,2],ppdoc_catalog:[0,1,2],ppdoc_crypt_pass:[0,1,2],ppdoc_crypt_statu:[0,1,2],ppdoc_fil:2,ppdoc_file_s:[0,1,2],ppdoc_filehandl:[1,2],ppdoc_first_pag:[0,1,2],ppdoc_fre:[0,1,2],ppdoc_info:[0,1,2],ppdoc_load:[0,1,2],ppdoc_mem:[0,1,2],ppdoc_memori:[0,1,2],ppdoc_next_pag:[0,1,2],ppdoc_object:[0,1,2],ppdoc_pag:[0,1,2],ppdoc_page_count:[0,1,2],ppdoc_permiss:[0,1,2],ppdoc_trail:[0,1,2],ppdoc_version_numb:[0,1,2],ppdoc_version_str:[0,1,2],ppdoc_xref:[0,1,2],ppint:[0,1,2],pplib:[2,4],pplib_author:2,pplib_vers:2,pplog_callback:[0,1,2],pplog_prefix:[0,1,2],pplogger_callback:[0,1,2],ppmatrix:[0,1,2],ppname:[0,1,2,4],ppname_data:[1,2,4],ppname_decod:[0,1,2,4],ppname_decoded_data:[1,2,4],ppname_encod:[0,1,2,4],ppname_encoded_data:[1,2,4],ppname_eq:[0,1,2],ppname_exec:[0,1,2],ppname_i:[0,1,2],ppname_s:[0,1,2,4],ppnone:[0,1,2],ppnull:[0,1,2],ppnum:[0,1,2],ppobj:[0,1,2],ppobj_get_:[0,1],ppobj_get_arrai:[0,1,2],ppobj_get_bool:[0,1,2],ppobj_get_bool_valu:2,ppobj_get_dict:[0,1,2],ppobj_get_int:[0,1,2],ppobj_get_int_valu:2,ppobj_get_nam:[0,1,2],ppobj_get_nul:[0,1,2],ppobj_get_num:[0,1,2],ppobj_get_num_valu:2,ppobj_get_ref:[0,1,2],ppobj_get_str:[0,1,2],ppobj_get_stream:[0,1,2],ppobj_get_uint:[0,1,2],ppobj_kind:2,ppobj_rget_:[0,1],ppobj_rget_arrai:2,ppobj_rget_bool:2,ppobj_rget_dict:[0,1,2],ppobj_rget_int:2,ppobj_rget_nam:2,ppobj_rget_nul:2,ppobj_rget_num:2,ppobj_rget_obj:[0,1,2],ppobj_rget_ref:2,ppobj_rget_str:2,ppobj_rget_stream:2,ppobj_rget_uint:2,ppobjtp:[0,1,2],pprect:[0,1,2],ppref:[0,1,2],ppref_obj:[0,1,2],ppstream:[0,1,2],ppstream_al:[0,1,2],ppstream_base16:[0,1,2],ppstream_base85:[0,1,2],ppstream_ccitt:[0,1,2],ppstream_compress:[0,1,2],ppstream_crypt:[0,1,2],ppstream_dct:[0,1,2],ppstream_dict:[0,1,2],ppstream_don:[0,1,2],ppstream_encrypt:[0,1,2],ppstream_encrypted_a:2,ppstream_encrypted_own:[0,1,2],ppstream_encrypted_rc4:2,ppstream_filt:[0,1,2],ppstream_filter_info:[0,1,2],ppstream_filter_nam:[0,1,2],ppstream_filter_typ:[0,1,2],ppstream_first:[0,1,2],ppstream_flat:[0,1,2],ppstream_free_buff:[0,1,2],ppstream_imag:[0,1,2],ppstream_init_buff:[0,1,2],ppstream_jbig2:[0,1,2],ppstream_jpx:[0,1,2],ppstream_lzw:[0,1,2],ppstream_next:[0,1,2],ppstream_not_support:2,ppstream_runlength:[0,1,2],ppstreamtp:[0,1,2],ppstring:[0,1,2,4],ppstring_base16:[0,1,2],ppstring_base85:[0,1,2],ppstring_data:[1,2,4],ppstring_decod:[0,1,2,4],ppstring_decoded_data:[1,2,4],ppstring_encod:[0,1,2,4],ppstring_encoded_data:[1,2,4],ppstring_exec:2,ppstring_hex:[0,1,2],ppstring_intern:2,ppstring_plain:[0,1,2],ppstring_siz:[0,1,2,4],ppstring_typ:[0,1,2],ppstring_utf16b:[0,1,2],ppstring_utf16l:[0,1,2],ppstring_utf:[0,1,2],pptest3:2,ppuint:[0,1,2],ppxref:[0,1,2],ppxref_catalog:2,ppxref_find:[0,1,2],ppxref_info:2,ppxref_pag:2,ppxref_prev:[0,1,2],ppxref_trail:2,ppxsec:2,practis:[0,1],preceed:[0,1],precis:[0,1],predictor:2,prefer:[0,1,4],prefix:[0,1,2],present:[0,1],preserv:[0,1],pretend:0,pretti:[0,1,4],previou:[0,1],print:[0,1,2],print_info:2,print_result_filt:2,print_stream_info:2,printabl:[0,1],printf:[0,1,2],privat:4,probabl:[0,1],proce:[0,1],procee:[0,1],process:[0,1],produc:[0,1,2],prompt:[0,1],proper:[0,1,2],properli:4,properti:[0,1,2],protect:[0,1,2],provid:[0,1,4],psize:[0,1,2],pune:2,put:[0,1],queri:[0,1],quit:[0,1],rather:[0,1],raw:[0,1,2],read:[0,1],readabl:[0,1],reader:[0,1],readi:[0,1],real:[0,1],realli:[0,1],reason:[0,1],reclaim:[0,1,2],reconstruct:[0,1],rect:[0,1,2],rectangl:[0,1],redirect:[0,1],ref:[2,3],refer:[0,1,2],referenc:[0,1],refnum:2,refnumb:[0,1,2],relat:[0,1,4],releas:[0,1,2],relev:[0,1],reli:1,remain:[0,1],remov:4,replac:[0,1],repres:[0,1,4],request:2,resid:1,resolv:[0,1,2],resourc:[0,1],restor:[0,1],restrict:[0,1],result:[0,1],reus:[0,1],revers:[0,1],revis:[2,4],revolut:4,rework:2,rewrit:[0,1],root:[0,1],roughli:[0,1],runlength:[0,1],runlengthdecod:[0,1],sai:[0,1],same:[0,1],saniti:[0,1,2],scheme:[0,1],search:[0,1],second:[0,1],sect:2,secur:[0,1,2],see:[0,1],seem:4,segfault:[],segment:0,self:4,sens:0,separ:[0,1],serv:4,set:[0,1],sever:[0,1],sha2:2,should:[0,1,2],shouldn:[0,1,2],show:[0,1],sign:[0,1,2],signed:4,simpl:[0,1],simpli:[0,1],sinc:[0,1,4],singl:[0,1,4],size:[0,1,2,4],size_t:[0,1,2,4],sizenum:2,sizeof:[0,1,2],skip:2,small:[0,1],smarter:[0,1],some:[0,1,2,4],some_output:[0,1],someth:[0,1],somewher:[0,1],soon:0,sorri:[0,1,2],sourc:[0,1,2],space:[0,1],spec:[0,1],special:[0,1],specif:[0,1],sprintf:2,stack:[0,1],standalon:[0,1],start:[0,1],state:[0,1],statu:[0,1],stddef:2,stderr:[0,1,2],stdint:2,stdio:2,stdout:[0,1],still:[0,1,4],stock:4,stop:[0,1],storag:4,store:[0,1,4],stream:[2,3],string:[2,3],strip:[0,1],strlen:[0,1],struct:[0,1,2,4],structur:[0,1,4],style:0,suboptim:[0,1],subsequ:[0,1],succe:[0,1],succeed:[0,1],suffer:[0,1],suit:[0,1,4],sum:[0,1,2],support:[0,1],surround:[0,1],sync:4,syntax:[0,1],tab:[0,1,2],tabl:[0,1],take:[0,1,4],taken:2,target:[0,1],tech:2,tell:[0,1],templat:[0,1,2],termin:[0,1],termini:0,test:2,text:[0,1],than:[0,1],thank:2,thei:[0,1,4],them:[0,1],thi:[0,1,2,4],think:[0,1],those:[0,1],though:0,through:[0,1],tiff:2,todo:3,tollbox:4,top:[0,1],toxic:2,trailer:[0,1],transform:[2,3],treat:[0,1],tree:[0,1],tri:[0,1],trick:4,trickeri:[0,1,4],trimbox:2,triplet:[0,1],trivial:4,two:[0,1,4],type:[2,3,4],typedef:[0,1,2],typic:[0,1],uint8_t:[0,1,2,4],unalign:4,uncompress:2,unconst:[0,1],undocu:[0,1],unescap:[0,1],unicod:[0,1],unif:4,union:[0,1,2],unless:[0,1],unnecesari:[0,1],unnecessari:[0,1],unread:[0,1],unsign:[0,1,2,4],unsupport:[0,1],until:[0,1],unus:4,updat:[0,1,2],usabl:4,usag:[0,1,2],use:[0,1,4],use_buffers_pool:2,used:[0,1,4],useless:[0,1],userpass:[0,1,2],userpasslength:[0,1,2],uses:[0,1,4],using:[0,1],usual:[0,1],utf16:[0,1],utf16b:[0,1],utf16l:[0,1],util:[0,1,2,4],utiliof:2,utilmem:4,utilmemallc:4,val:[0,1],valid:[0,1],valu:[0,1],variabl:[0,1],variant:4,verbos:[0,1],verifi:[0,1],version:[0,1,2,4],via:[0,1,4],wai:[0,1],want:[0,1,4],warn:[2,4],wast:[0,1,2],watch:4,well:[0,1,4],were:4,weren:[0,1,2],what:[0,1],whatev:[0,1],when:[0,1,2],whenev:[0,1,4],which:[0,1,4],window:4,without:[0,1],wntri:[0,1],won:[0,1],word:[0,1,2,4],work:4,would:[0,1],write:2,wrong:[0,1,4],xref:[2,3],xsec:2,yes:[0,1],yet:4,you:[0,1],your:[0,1],your_callback:[0,1],yourself:[0,1],zero:[0,1]},titles:["<code class=\"docutils literal notranslate\"><span class=\"pre\">pplib</span></code> 1.x","<code class=\"docutils literal notranslate\"><span class=\"pre\">pplib</span></code> 2.x","Examples","pplib","1.x vs 2.x"],titleterms:{And:4,alloc:4,api:[0,1],arrai:[0,1],box:[0,1],chang:2,cleanup:4,content:[0,1],dict:[0,1],encrypt:[0,1],error:[0,1],exampl:2,filter:[0,1],handl:[0,1],name:[0,1,4],object:[0,1],page:[0,1],pdf:[0,1],ppapi:2,pplib:[0,1,3],ref:[0,1],stream:[0,1],string:[0,1,4],todo:2,transform:[0,1],type:[0,1],xref:[0,1]}})
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/conf.py b/Build/source/texk/web2c/luatexdir/luapplib/doc/conf.py new file mode 100644 index 00000000000..cc74378cb1e --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/conf.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = u'pplib' +copyright = u'2019, p.jackowski@gust.org.pl' +author = u'p.jackowski@gust.org.pl' + +# The short X.Y version +version = u'' +# The full version, including alpha/beta/rc tags +release = u'0.1' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'pplib' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path . +exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +#html_theme = 'alabaster' +html_theme = 'bizstyle' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'pplibdoc' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'pplib.tex', u'pplib Documentation', + u'p.jackowski@gust.org.pl', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'pplib', u'pplib Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'pplib', u'pplib Documentation', + author, 'pplib', 'One line description of project.', + 'Miscellaneous'), +]
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/make.bat b/Build/source/texk/web2c/luatexdir/luapplib/doc/make.bat new file mode 100644 index 00000000000..b1e0e54b1c0 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/make.bat @@ -0,0 +1,36 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build +set SPHINXPROJ=pplib + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/ppapi-1.x.rst b/Build/source/texk/web2c/luatexdir/luapplib/doc/ppapi-1.x.rst new file mode 100644 index 00000000000..df661a7b82d --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/ppapi-1.x.rst @@ -0,0 +1,937 @@ +
+``pplib`` 1.x
+=============
+
+``pplib`` is a library for raw PDF access. It parses PDF documents and provides an interface to access document structures in C.
+
+C-API
+=====
+
+Types
+-----
+
+``pplib`` defines several C-types to represent PDF types:
+
+- ``ppint`` - signed integer (``int64_t``)
+- ``ppnum`` - real number (double)
+- ``ppname`` - PDF name
+- ``ppstring`` - PDF string
+- ``pparray`` - PDF array
+- ``ppdict`` - PDF dict
+- ``ppstream`` - PDF stream
+- ``ppref`` - PDF indirect reference
+- ``ppobj`` - a container of all above
+
+Among ``ppint`` and ``ppnum``, we also use ``ppuint`` - unsigned integer (machine word, alias to ``size_t``).
+
+Other API types:
+
+- ``ppdoc`` - PDF document
+- ``ppxref`` - cross-references table
+- ``ppcontext`` - ... later
+- ``pprect`` - rectangle
+- ``ppmatrix`` - matrix
+
+Integer, number, name and string are treated as simple types.
+Names and strings are actually C-structures, but exposed to API as typedefs to ``const char *``.
+Other types (array, dict, stream, reference, object container, xref, PDF) are C-structures,
+and you operate it their pointers. So when you declare a simple type variable you say::
+
+ ppuint u;
+ ppnum n;
+ ppname name;
+ ppstring string;
+ ...
+
+And when you declare a compound type you operate on pointers::
+
+ ppobj *obj;
+ pparray *array;
+ ppdict *dict;
+ ppstream *stream;
+ ppref *ref;
+ ppdoc *pdf;
+
+Some of those C-types are defined in library header ``ppapi.h`` (complete types). Some others are incomplete
+(eg. you can't say ``sizeof(ppdoc)`` or ``sizeof(ppxref)``). This is to avoid unnecesary dependencies in
+the header. [At some points it's not clear to me what to hide and what to expose, will see.] The library itself
+uses ``pplib.h`` but for auxilary applications including a standalone ``ppapi.h`` header should be enough.
+
+``pplib`` was designed having **read-only** PDF access in mind. Even if some structure is completelly exposed,
+so that you can directly access its members, you should treat them as read-only. I don't make them ``const`` because
+then all variable declarations would need to be ``const``, which is annoying, and I'd need some trickery in the library
+internals to unconst. Besides, nothing is really const for C type casts.
+
+Object
+------
+
+A common container for all elementary PDF object types is ``ppobj`` structure. ``ppobj`` has a type identifier
+(integer) and union of values::
+
+ struct ppobj {
+ ppobjtp type;
+ union {
+ ppint integer;
+ ppnum number;
+ ppname name;
+ ppstring string;
+ pparray *array;
+ ppdict *dict;
+ ppstream *stream;
+ ppref *ref;
+ void *any;
+ };
+ };
+
+Object type is one of constants (enum)::
+
+ PPNONE
+ PPNULL
+ PPBOOL
+ PPINT
+ PPNUM
+ PPNAME
+ PPSTRING
+ PPARRAY
+ PPDICT
+ PPSTREAM
+ PPREF
+
+The type determines the structure member you're allowed to access::
+
+ ppobj *obj;
+ ...
+ switch (obj->type)
+ {
+ case PPNONE: // shouldn't actually happen, indicates some failure
+ break;
+ case PPNULL: // valid PDF null object, no value
+ break;
+ case PPBOOL: // do something with obj->integer (ppint), value 0 or 1
+ break;
+ case PPINT: // do something with obj->integer (ppint)
+ break;
+ case PPNUM: // do something with obj->number (ppnum)
+ break;
+ case PPNAME: // do something with obj->name (ppname)
+ break;
+ case PPSTRING: // do something with obj->string (ppstring)
+ break;
+ case PPARRAY: // do something with obj->array (pparray *)
+ break;
+ case PPDICT: // do something with obj->dict (ppdict *)
+ break;
+ case PPSTREAM: // do something with obj->stream (ppstream *)
+ break;
+ case PPREF: // do something with obj->ref (ppref *)
+ break;
+ }
+
+More often then not you know exactly what type of object value is expected, in which case
+you may use one of the following macros::
+
+ // returns 1 if o->type is PPNULL
+ int ppobj_get_null(o) \
+
+ // if o->type is PPBOOL, sets int v to 0 or 1 and returns 1, 0 otherwise
+ int ppobj_get_bool(o, v)
+
+ // if o->type is PPINT, sets ppint v and returns 1, 0 otherwise
+ int ppobj_get_int(o, v)
+
+ // if o->type is PPINT and >= 0, sets ppuint v and returns 1, 0 otherwise
+ int ppobj_get_uint(o, v)
+
+ // if o->type is PPNUM or PPINT, sets ppnum v and returns 1, 0 otherwise
+ int ppobj_get_num(o, v)
+
+ // if o->type is PPNAME returns the name, NULL otherwise
+ ppname ppobj_get_name(o)
+
+ // if o->type is PPSTRING returns the string, NULL otherwise
+ ppstring ppobj_get_string(o)
+
+ // if o->type is PPARRAY returns the array, NULL otherwise
+ pparray * ppobj_get_array(o)
+
+ // if o->type is PPDICT returns the dict, NULL otherwise
+ ppdict * ppobj_get_dict(o)
+
+ // if o->type is PPSTREAM returns the stream, NULL otherwise
+ ppstream * ppobj_get_stream(o)
+
+ // if o->type is PPREF returns the reference, NULL otherwise
+ ppref * ppobj_get_ref(o)
+
+Note the coercion from integer to real number, but not reverse. In practise, whenever you expect a real number,
+you should also handle integer (eg. '1' used instead of '1.0').
+
+It is a common case that the object is given as an indirect reference, but what you actually
+want is not the reference, but the object referred by it. Here is a helper for it::
+
+ // if o->type is PPREF, returns what the reference points, otherwise returns o
+ ppobj * ppobj_rget_obj(o)
+
+Also every ``ppobj_get_*`` macro has ``ppobj_rget_*`` counterpart that makes a check
+for the expected type, but if the object is PPREF, it jumps to the target object.
+So for example ``ppobj_rget_dict(obj)`` will return dict if ``obj`` is of type PPDICT
+or if it is of type PPREF and ``obj->ref`` hosts an object of type PPDICT.
+
+Names
+-----
+
+PDF names are represented as ``ppname``.
+I find it convenient to have ``ppname`` type pretending ``const char *``. This allows to use ``ppname``
+in all C-style string functions like ``printf("%s", name)``.
+
+Be aware, however, that ``ppname`` is actually a C-structure. It is perfectly ok to cast ``ppname`` to ``const char *``::
+
+ ppname name;
+ ...
+ (const char *)name;
+
+But reverse is forbidden::
+
+ const char *cstr = "cstring";
+ ...
+ (ppname)cstr; // expect segmentation fault soon
+
+For convenient use in C, names are ``'\0'`` terminated. But to get the length of name better always use
+``ppname_size()`` macro. ``ppname`` object knows its size, don't use ``strlen()``::
+
+ size_t ppname_size(ppname name); // macro, returns length of name in bytes
+
+In current implementation names are not hashed anyhow, so name-to-name comparison is not smarter than ``memcmp()``.
+Use macros::
+
+ int ppname_is(ppname name, "literal"); // to compare ppname with C-literal string
+ int ppname_eq(ppname name, ppname other); // to compare ppname with a different name
+
+If you'll use ``pplib`` to parse contents streams, you may need to distinguish names from operators
+(more precisely executable names). Names in PDF are preceeded by '/', executable names aren't. In both
+cases PDF parser will produce ``ppname`` but can be distingushed with::
+
+ int ppname_exec(ppname name); // returns non-zero if name is executable
+
+Names are kept in their raw form, with possible PDF specific escapes (in text below we call it **encoded** form).
+Leading '/' is omitted, though. One may need a decoded name, with no PDF escapes.
+A pair of functions provides a simple interface to switch between those two forms::
+
+ ppname ppname_decoded (ppname name); // returns decoded (unescaped) form of the name
+ ppname ppname_encoded (ppname name); // returns encoded (escaped) form of the name
+
+In pretty most cases PDF names contains only letters (no special characters, no escapes), so decoded and encoded forms are identical.
+In that case both functions simply return the argument. It is ok to call ``ppname_decoded()`` on already decoded form
+and ``ppname_encoded()`` on already encoded form. Both forms are produced by PDF objects parser, so accessing ``ppname`` alter ego
+in whatever direction needs no extra decoding or allocation costs.
+
+String
+------
+
+PDF strings have the same internal construction as names, so most of names description above applies to strings as well.
+``ppstring`` is a typedef of ``const char *``, roughly ``'\0'`` terminiated C-string. To get the size of the string::
+
+ size_t ppstring_size(ppstring string); // macro, returns the length of the string in bytes
+
+Strings are provided in their raw form, preserving PDF specific escapes, but with no
+``()`` or ``<>`` delims. To distinguish plain strings from hex strings::
+
+ int ppstring_hex(ppstring string); // macro, returns non zero if hex string
+
+Or if you prefer::
+
+ switch (ppstring_type(string))
+ {
+ case PPSTRING_PLAIN: // literal string, surrounded by ``(`` and ``)`` in PDF
+ break;
+ case PPSTRING_BASE16: // hex string, surrounded by ``<`` and ``>`` in PDF
+ break;
+ case PPSTRING_BASE85: // base85 string surrounded by ``<~`` and ``~>`` in PDF
+ break;
+ }
+
+The last is actually Postscript specific, not used in PDF, but I think it might appear in contents streams...
+No matter how the string is given in PDF (plain or hex), here are two functions to
+switch between encoded and decoded strings forms::
+
+ ppstring ppstring_decoded (ppstring string); // returns decoded string possibly with PDF escapes
+ ppstring ppstring_encoded (ppstring string); // returns encoded string with no PDF escapes
+
+For hex strings, encoded form contains hex digits, while decoded form contains arbitrary bytes (the result of hex decoding).
+Plain strings usually contains printable ASCII characters, but they might contain any binary data.
+As with names, objects parser produces both forms. The raw form with PDF escapes (or raw hex form) is considered the main one.
+Eg. when you access ``obj->string`` you always get the encoded form. At any moment you can switch to its alter ego.
+
+No matter if the string is plain or hex, if its first two bytes (decoded) are UTF16 BOM, the string
+is considered unicode. ``ppstring`` object *knows* it is unicode or not::
+
+ switch (ppstring_utf(string))
+ {
+ case PPSTRING_UTF16LE: // unicode string, utf16le
+ break;
+ case PPSTRING_UTF16BE: // unicode string, utf16be
+ break;
+ default: // no unicode
+ }
+
+Or simply::
+
+ if (ppstring_utf(string) != 0) {
+ // handle unicode string
+ }
+
+If the string is unicode, BOM remains the part of the string -- ``pplib`` parser does not strip it.
+Unicode or not, encoded or decoded, strings are always C-arrays of bytes and ``ppstring_size()``
+always returns the size in bytes.
+
+Array
+-----
+
+PDF arrays are represented as ``pparray`` type, which is C-array of ``ppobj`` structures.
+To get the size::
+
+ size_t pparray_size(pparray *array) // macro, returns the number of array items
+
+To get ``ppobj *`` at a given index::
+
+ ppobj * pparray_at(array, index) // macro, returns ppobj * (no index check)
+ ppobj * pparray_get(array, index) // macro, returns ppobj * or NULL (with index check)
+ ppobj * pparray_get_obj (pparray *array, size_t index); // function equiv to pparray_get()
+
+Iterating over array elements::
+
+ pparray *array;
+ size_t index, size;
+ ppobj *obj;
+ for (size = pparray_size(array), pparray_first(array, index, obj); index < size; pparray_next(index, obj))
+ {
+ // do something with index and obj
+ }
+
+There is no magic first/next macros, just iteration over pointers. One could also use something like::
+
+ for (index = 0, size = array->size; index < size; ++index)
+ {
+ obj = pparray_at(array, index);
+ // do something with index and obj
+ }
+
+When getting values from array and expecting a result of known type, use one of the following::
+
+ int pparray_get_bool (pparray *array, size_t index, int *v); // get boolean value
+ int pparray_get_int (pparray *array, size_t index, ppint *v); // get ppint value
+ int pparray_get_uint (pparray *array, size_t index, ppuint *v); // get ppuint value
+ int pparray_get_num (pparray *array, size_t index, ppnum *v); // get ppnum value
+ ppname pparray_get_name (pparray *array, size_t index); // get ppname value
+ ppstring pparray_get_string (pparray *array, size_t index); // get ppstring value
+ pparray * pparray_get_array (pparray *array, size_t index); // get pparray * value
+ ppdict * pparray_get_dict (pparray *array, size_t index); // get ppdict * value
+ ppref * pparray_get_ref (pparray *array, size_t index); // get ppref * value
+
+As with ``ppobj_get_*`` suite, numeric types getters set the value of a given type and returns 1, if the type matches.
+Otherwise sets nothing and returns 0. Other getters return the value if the type matches, or NULL.
+
+Every function from ``pparray_get_*`` suite have its ``pparray_rget_*`` counterpart that
+that dereferences indirect objects (as explained for ``ppobj_rget_*`` getters). Note that
+there is no ``pparray_get_stream()`` function, as streams in PDF are always indirect.
+To get the stream from array use::
+
+ ppstream * pparray_rget_stream (pparray *array, size_t index);
+
+Dict
+----
+
+PDF dicts are represented as ``ppdict`` structure, which is C-array of ``ppobj`` with parallel
+C-array of ``ppname`` pointers. To get the size of a dict::
+
+ size_t ppdict_size(ppdict *dict) // macro, returns the number of key-val pairs
+
+To get the value at a given index (integer)::
+
+ ppobj * ppdict_at(ppdict *dict, index) // macro, no index check
+
+To get the name (key) at a given index::
+
+ ppname ppdict_key(ppdict *dict, index) // macro, no index check
+
+To iterate over dict key-val pairs::
+
+ ppdict *dict;
+ ppname *pkey;
+ ppobj *obj;
+
+ for (ppdict_first(dict, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj))
+ {
+ // do something with *pkey and obj
+ }
+
+There is no magic in first/next macros, just iteration through keys and values lists pointers.
+For convenient iteration, a list of keys is terminated with NULL, so in the code above ``*pkey != NULL``
+is used as the loop condition. One may also iterate via indices::
+
+ ppdict *dict;
+ size_t index, size;
+ ppname key;
+ ppobj *obj;
+ for (index = 0, size = ppdict_size(dict); index < size; ++index)
+ {
+ key = ppdict_key(dict, index);
+ obj = ppdict_at(dict, index);
+ // do something with key and obj
+ }
+
+To get the object associated with a given name, use one of the following::
+
+ ppobj * ppdict_get_obj (ppdict *dict, const char *name);
+ int ppdict_get_bool (ppdict *dict, const char *name, int *v);
+ int ppdict_get_int (ppdict *dict, const char *name, ppint *v);
+ int ppdict_get_uint (ppdict *dict, const char *name, ppuint *v);
+ int ppdict_get_num (ppdict *dict, const char *name, ppnum *v);
+ ppname ppdict_get_name (ppdict *dict, const char *name);
+ ppstring ppdict_get_string (ppdict *dict, const char *name);
+ pparray * ppdict_get_array (ppdict *dict, const char *name);
+ ppdict * ppdict_get_dict (ppdict *dict, const char *name);
+ ppref * ppdict_get_ref (ppdict *dict, const char *name);
+
+Note that all getters accepts ``const char *`` as key, so it is ok to say::
+
+ ppdict_rget_dict(dict, "Resources");
+
+as well as::
+
+ ppdic_rget_dict(dict, name); // ppname name
+
+Every ``ppdict_get_*`` getter has ``ppdict_rget_*`` counterpart that dereferences
+indirect objects if necessary. Note that there is no ``ppdict_get_stream()`` function,
+but there is::
+
+ ppstream * ppdict_rget_stream (ppdict *dict, const char *name);
+
+So far dicts comes with no names mapping, so by-name dict accessors perform a linear search
+through the keys list. PDF dicts are usually small, so it is fast enough.
+Building names lookup for every dict in PDF makes no sense I think, as ``pplib`` applications
+will query just several dicts I guess.. However, some apps may extensively query
+resources, which may refer to hundreds of objects (eg. images). So some mapping for dicts
+is still considered.
+
+Stream
+------
+
+PDF streams are represented as ``ppstream`` objects. To get the stream dict::
+
+ ppdict * ppstream_dict(ppstream *stream) // macro
+
+To read the stream data::
+
+ uint8_t * ppstream_first (ppstream *stream, size_t *size, int decode);
+ uint8_t * ppstream_next (ppstream *stream, size_t *size);
+ void ppstream_done (ppstream *stream);
+
+Both ``first` and ``next`` functions return a chunk of stream data and sets the ``size`` of the chunk.
+``decode`` parameter tell the reader to decompress the stream (1) or return raw (0). A call to ``ppstream_next()``
+must be preceeded by ``ppstream_first()``. Once you're done with the stream, you have to call ``ppstream_done()``,
+no matter if the stream has been read to the end or not. The stream data iterator in use::
+
+ uint8_t *data;
+ size_t size;
+ ppstream *stream;
+ int decode = 1; // 1 - get decompressed, 0 - get raw
+
+ for (data = ppstream_first(stream, &size, decode); data != NULL; data = ppstream_next(stream, &size))
+ {
+ // do something with data and its size
+ }
+ ppstream_done(stream);
+
+Every subsequent iterator call invalidates the previous reader output, so you have to utilize the returned chunk
+of data just after you ot that. So the following is wrong::
+
+ data1 = ppstream_first(stream, &size, 1);
+ data2 = ppstream_next(stream, &size);
+ data3 = ppstream_next(stream, &size);
+ some_output(data1, size);
+ some_output(data2, size);
+
+The reader calls usually return the same pointer to internal buffer, just filled with a different data.
+``pplib`` allocates reasonably large buffer and fills that buffer on subsequent calls to the reader.
+
+If the source stream has no compression, using both ``decode == 1`` and ``decode == 0`` should give the same result.
+You can check if the stream is actually compressed with::
+
+ ppstream_compressed(stream) // macro, returns non zero if /Filter is present
+
+It might be necessary to load the entire stream data at once::
+
+ uint8_t * ppstream_all (ppstream *stream, size_t *size, int decode);
+
+If the initial buffer size is insufficient, it grows until the entire stream data is loaded. You must call
+``ppstream_done(stream)`` after using returned data.
+
+``ppstream_done()`` doesn't invalidate the stream object, it just closes its internal reader.
+The stream itself remains a valid object (eg. one can read it again if necessary),
+but the reader buffer is released. It is actually not freed but kept for future the reuse with that on some other stream,
+but you still need to mark it ready for reuse to avoid allocating a separate buffer for every stream you're going to read.
+
+Stream data readers will return ``NULL`` if you haven't close the previous reader process with ``ppstream_done()``. All below is wrong::
+
+ data1 = ppstream_all(stream, &size, 1);
+ data2 = ppstream_all(stream, &size, 1); // data2 == NULL
+ // or
+ data1 = ppstream_first(stream, &size, 1);
+ data2 = ppstream_first(stream, &size, 1); // data2 == NULL
+ // or
+ data1 = ppstream_first(stream, &size, 1);
+ data2 = ppstream_all(stream, &size, 1); // data2 == NULL
+
+To avoid unnecessary dependencies, ``pplib`` does not support image filters (``/DCT``, ``/JPX``, ``/JBIG``, ``/CCITT``).
+But it is ok to read the stream with ``decode`` set to 1 on such streams. ``pplib`` assumes that the image is the
+final/target stream form and just returns it as-is. Eg. in the case of JPEG (``/DCT`` filtered) image both calls should
+give the same results::
+
+ ppstream_all(jpegstream, &jpegsize, 0); // don't decode, return what's there
+ ppstream_all(jpegstream, &jpegsize, 1); // decode but found image filter, effectively the same
+
+A bit more about streams memory. As mentioned, ``pplib`` allocates buffers for stream readers. After ``ppstream_done()``,
+the stream no longer *owns* the buffer space. But the buffer may remain allocated, to be reused with future readers.
+``pplib`` keeps a pool of several buffers. This means, that when you use stream readers, ``pplib`` eats
+some memory (1MB or so) that is not freed, even if no streams are used. And even if you free all objects.
+If you suffer from this, you can optionally use a pair of functions::
+
+ void ppstream_init_buffers (void);
+ void ppstream_free_buffers (void);
+
+The first initializes buffers pool, unless done so far. Currently ``pplib`` cares of it before opening every stream reader,
+so it is not obligatory. The second frees a pool of buffers. The intended use is to call ``ppstream_init_buffers()`` once
+as kind of library initializer and to call ``ppstream_free_buffers()`` once, as the library finalizer.
+
+Filters
+-------
+
+In version v1.00 (20190916) ``ppstream`` API has been extended with filters information.
+``ppstream`` knows its filter(s) and keps it as ``stream->filter``::
+
+ // ppstream *stream;
+ ppstream_filter *info = &stream->filter;
+
+``ppstream_filter`` is the following structure::
+
+ typedef struct {
+ ppstreamtp *filters; // c-array of filter identifiers (enum integers)
+ ppdict **params; // c-array of ppdict pointers
+ size_t count; // number of filters, length of the arrays (typically 1)
+ } ppstream_filter;
+
+If ``count > 0`` then ``filters`` member is not NULL. Filters array keeps integer constants::
+
+ PPSTREAM_BASE16 /* /ASCIIHexDecode */
+ PPSTREAM_BASE85 /* /ASCII85Decode */
+ PPSTREAM_RUNLENGTH /* /RunLengthDecode */
+ PPSTREAM_FLATE /* /FlateDecode */
+ PPSTREAM_LZW /* /LZWDecode */
+ PPSTREAM_CCITT /* /CCITTFaxDecode */
+ PPSTREAM_DCT /* /DCTDecode */
+ PPSTREAM_JBIG2 /* /JBIG2Decode */
+ PPSTREAM_JPX /* /JPXDecode */
+ PPSTREAM_CRYPT /* /Crypt */
+
+Params array keeps corresponding filter parameters (``/DecodeParms``) if present. ``params`` member is not NULL
+if ``count > 0`` and the stream dict has ``/DecodeParms`` entry. Even if ``params`` is there,
+for every N-th filter, ``params[N]`` may be NULL (corresponding to PDF ``null``).
+
+``stream->filter`` keeps the source stream filter information, which may not correspond to the result of stream readers
+(``ppstream_first()``, ``ppstream_next()``, ``ppstream_all()``). The get the filters info relevant to the result from readers::
+
+ void ppstream_filter_info (ppstream *stream, ppstream_filter *info, int decode);
+
+The function fills ``ppstream_filter`` structure according to the expected result from stream readers (example 3 shows
+how to use it to reconstruct ``/Filter`` and ``/DecodeParms`` when copying the stream to some other PDF).
+
+To convert filter identifier (``ppstreamtp``) to a corresponding PDF filter name::
+
+ const char * ppstream_filter_name[];
+
+To covert ``ppname`` to filter identifier::
+
+ int ppstream_filter_type (ppname filtername, ppstreamtp *filtertype);
+ // returns 1 and sets filtertype if filtername is the proper filter name
+
+Additional information about the stream can be fetched from macros::
+
+ ppstream_compressed(stream) /* stream->flags & (PPSTREAM_FILTER|PPSTREAM_IMAGE) */
+ ppstream_filtered(stream) /* stream->flags & PPSTREAM_FILTER */
+ ppstream_image(stream) /* stream->flags * PPSTREAM_IMAGE */
+
+``stream->flags`` is a binary sum of the following::
+
+ PPSTREAM_FILTER /* set iff the stream filters list has one of: BASE16, BASE85, RUNLENGTH, FLATE, LZW */
+ PPSTREAM_IMAGE /* set iff the stream filters list has one of: CCITT, DCT, JBIG2, JPX */
+ PPSTREAM_ENCRYPTED /* set iff the stream is encrypted */
+ PPSTREAM_ENCRYPTED_OWN /* set iff the stream has own CRYPT filter */
+
+Note that ``PPSTREAM_COMPRESSED`` is not there any longer, use ``ppstream_compressed()`` instead.
+And there is some more, see ``ppapi.h``.
+
+Ref
+---
+
+Indirect objects are represented as ``ppref`` structure. To get the object that the
+reference refers to::
+
+ ppobj * ppref_obj(ppref *ref) // macro
+
+``ppref`` structure also keeps the reference number and version, a pointer to cross reference table it belongs
+to and others, but I guess you won't need anything but the referenced object. ``pplib`` parser resolves references
+on-fly. So if there is a dict with indirect objects::
+
+ <<
+ /Type /Page
+ /Resources 123 0 R
+ ...
+ >>
+
+the parser will produce ``ppdict`` with ``Resources`` key pointing the proper ``ppref *`` value.
+If you need more, access ``ppref`` members::
+
+ struct ppref {
+ ppobj object; // target object
+ ppuint number, version; // identifiers
+ size_t offset; // file offset (useless for you, may be zero for compressed objects)
+ ppuint length; // the length of the original object data
+ ppxref *xref; // cross reference table it belongs to
+ };
+
+
+XRef
+----
+
+Cross reference table is exposed as ``ppxref`` (incomplete type, you can only oprate on its pointer).
+To get top document xref::
+
+ ppxref * ppdoc_xref (ppdoc *pdf);
+
+To get previous (older) xref::
+
+ ppxref * ppxref_prev (ppxref *xref);
+
+To find an object of a given refnumber::
+
+ ppref * ppxref_find (ppxref *xref, ppuint refnumber);
+
+[Note: since pplib v0.98 in case of documents with incremental update, ``ppxref_find()`` returns
+the newest available version of a given object rather than the object in a given body.]
+
+PDF
+---
+
+PDF document is represented as ``ppdoc`` structure (incomplete type, you can only operate on its pointer).
+To load a document from file::
+
+ ppdoc * ppdoc_load (const char *filename);
+
+To load a document from memory data::
+
+ ppdoc * ppdoc_mem (const void *data, size_t size);
+
+The data is assumed to be a buffer allocated with ``malloc`` - it is freed when destroying ``ppdoc``.
+
+Both loaders returns ``NULL`` on failure.
+
+To free ``ppdoc`` and all objects it refers to::
+
+ void ppdoc_free (ppdoc *pdf);
+
+So far we haven't mention about any explicit object reclaimers. There are no dedicated ``free`` functions
+for other objects. You don't allocate or free objects yourself. ``ppdoc`` object is an owner of all
+beings it refers to. It also means that every object described so far is alive as long as the containing
+``ppdoc`` is alive.
+
+To access main PDF dicts::
+
+ ppdict * ppdoc_trailer(ppdoc *pdf); // returns top xref trailer dict
+ ppdict * ppdoc_catalog(ppdoc *pdf); // returns catalog referred from the trailer
+ ppdict * ppdoc_info(ppdoc *pdf); // returns info dict referred from the trailer
+
+To get the PDF version::
+
+ const char * ppdoc_version_string (ppdoc *pdf); // version string
+ int ppdoc_version_number (ppdoc *pdf, int *minor); // minor and major numbers
+
+To get the file size of the source PDF document::
+
+ size_t ppdoc_file_size (ppdoc *pdf);
+
+To get the number of objects in all xrefs::
+
+ ppuint ppdoc_objects (ppdoc *pdf);
+
+To get the approx usage of memory::
+
+ size_t ppdoc_memory (ppdoc *pdf, size_t *waste);
+
+Encryption
+----------
+
+``pplib`` handles encrypted (password protected) documents. If a document is encrypted, most of strings and streams are ciphered.
+In that form they are unreadable and rather useless, you can't even rewrite such strings/streams as-is to a different PDF output.
+It is a common practise to *protect* documents with an empty password. Such documents remain readable in Acrobat (just opens them without prompting
+for a password), but some features (eg. printing) may restricted by the application.
+
+When ``pplib`` detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, ``pplib`` proceeeds normally, providing
+an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, ``pplib`` gives
+a way to provide a password and proceed. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object wntries
+set to ``null``.
+
+After loading a document you should check encryption status with::
+
+ ppcrypt_status ppdoc_crypt_status (ppdoc *pdf);
+
+``ppcrypt_status`` (integer) may have the following values:
+
+ ``PPCRYPT_NONE`` - no encryption, go ahead
+ ``PPCRYPT_DONE`` - encryption present but password succeeded, go ahead
+ ``PPCRYPT_PASS`` - encryption present, need non-empty password
+ ``PPCRYPT_FAIL`` - invalid or unsupported encryption (eg. undocumented in pdf spec)
+
+If a password is needed, you can provide one with::
+
+ ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength,
+ const void *ownerpass, size_t ownerpasslength);
+
+Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough
+to know that having one of them is enough to decrypt the document. If you know the password, you probably mean
+``userpass``, in which case you should put ``NULL`` as ``ownerpass``. The function returns ``PPCRYPT_DONE`` if the password
+succeeds and the previous status otherwise. Your custom loader function may look like that::
+
+ ppdoc *pdf;
+ pdf = ppdoc_load("file.pdf");
+ if (pdf == NULL)
+ return NULL;
+ switch (ppdoc_crypt_status(pdf))
+ {
+ case PPCRYPT_NONE:
+ case PPCRYPT_DONE:
+ return pdf;
+ case PPCRYPT_PASS:
+ if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE ||
+ ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE)
+ return pdf;
+ printf("sorry, password needed\n");
+ ppdoc_free(pdf);
+ return NULL;
+ case PPCRYPT_FAIL:
+ printf("sorry, encryption failed\n");
+ ppdoc_free(pdf);
+ return NULL;
+ }
+
+[If you get ``PPCRYPT_FAIL`` it might mean *I failed*, so treat as a bug.]
+
+If you'd like to know what permissions are given/restricted to encrypted document::
+
+ ppint ppdoc_permissions (ppdoc *pdf);
+
+Returned value can be queried with the following binary flags (you can verify with Acrobat *File -> Properties -> Security* tab)::
+
+ PPDOC_ALLOW_PRINT // printing
+ PPDOC_ALLOW_MODIFY // filling form fields, signing, creating template pages
+ PPDOC_ALLOW_COPY // copying, copying for accessibility
+ PPDOC_ALLOW_ANNOTS // filling form fields, copying, signing
+ PPDOC_ALLOW_EXTRACT // contents copying for accessibility
+ PPDOC_ALLOW_ASSEMBLY // (no effect)
+ PPDOC_ALLOW_PRINT_HIRES // (no effect)
+
+``pplib`` does absolutelly nothing with permissions, it cares only to decrypt the document. As mentioned, encryption applies to strings
+and streams. ``pplib`` decrypt strings when parsing document objects, so the result you get is *normal* (not ciphered).
+Streams are decrypted whenever you access them. Even if you ask for a raw stream data, you'll get a raw (compressed) stream, but decrypted.
+So except the check to ``ppdoc_crypt_status()``, you shouldn't bother about encryption.
+
+In encrypted documents most of streams are encrypted. To check if a given stream is encrypted::
+
+ ppstream_encrypted(stream) // macro, returns non-zero if encrypted
+
+Encryption is independent from compression, don't confuse with ``ppstream_compressed()``
+
+Pages
+-----
+
+Several helpers to deal with pages. To get the number of pages::
+
+ ppuint ppdoc_page_count (ppdoc *pdf);
+
+To access the root pages tree node::
+
+ ppref * ppdoc_pages(ppdoc *pdf);
+
+To get the page reference at a given index::
+
+ ppref * ppdoc_page (ppdoc *pdf, ppuint index);
+
+``index`` is a page number. First page has number 1. For index out of bounds ``ppdoc_page()`` returns NULL.
+Iterating over pages using index from 1 to ``ppdoc_page_count()`` and calling ``ppdoc_page()`` on each iteration
+would be suboptimal. Here is a dedicted iterator for this::
+
+ ppref * ppdoc_first_page (ppdoc *pdf);
+ ppref * ppdoc_next_page (ppdoc *pdf);
+
+The iterator in use::
+
+ ppdoc *pdf;
+ ppref *ref;
+ ppdict *dict;
+ int pageno;
+
+ pdf = ppdoc_load("file.pdf");
+ for (ref = ppdoc_first_page(pdf), pageno = 1; ref != NULL; ref = ppdoc_next_page(pdf), ++pageno)
+ {
+ dict = ppref_obj(obj)->dict; // take for granted it is a dict
+ // do something with the page dict
+ }
+
+Functions related to pages return ``ppref *`` ensured to contain dict object, so you don't need sanity
+type checks here.
+
+Contents
+--------
+
+PDF page contents can be given as a stream or array of streams. Here is a convenience iterator over page
+contents streams::
+
+ ppstream * ppcontents_first (ppdict *dict);
+ ppstream * ppcontents_next (ppdict *dict, ppstream *stream);
+
+A complete example of contents stream parser use is given below (example 2).
+But before we get there, we need to introduce ``ppcontext`` object. Conceptually,
+``ppcontext`` is an owner (memory handler) of objects created on demand (beyond the ``ppdoc``).
+So far used only with contents stream parser, which might produce quite some data that we want
+to release just after used. To create a new context::
+
+ pcontext * ppcontext_new (void);
+
+It initializes a new context and its internal memory heap, taking about 64kB on start. After that,
+the context is ready to produce objects (contents parsing functions below). Once objects produced
+from a given context are no longer needed::
+
+ void ppcontext_done (ppcontext *context);
+
+It restores the context to its initial state, as after ``ppcontext_new()``. It means that the context
+is ready to produce another bunch of beings (in the example below, all objects from the next page contents).
+Once the context is not needed anymore::
+
+ void ppcontext_free (ppcontext *context);
+
+Now, contents stream parser functions take the context as an argument. Iterator form of contents stream parser
+that allows to process the contents operator by operator::
+
+ ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname);
+ ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname);
+
+Returned ``ppobj *`` is a pointer to operands list. ``*psize`` is the number of operands on stack.
+The operator itself is stored as ``*pname``.
+
+To parse the entire contents stream at once with no stop at every operator::
+
+ ppobj * ppcontents_parse (ppcontext *context, ppstream *stream, size_t *psize);
+
+Returns probably quite long list of all parsed objects (operands and operatos) in one piece.
+The number of objects is stored to ``*psize``.
+
+[Contents may contain so called inline images, that breaks a simple scheme of operands / operator syntax::
+
+ BI <keyval pairs> ID <binary image data> EI
+
+Contents parser treats this genuine triplet as a single piece, producing two operands (dict and string)
+followed by ``EI`` operator name.]
+
+Boxes
+-----
+
+Boxes (rectangles) in PDF are roughly 4-number arrays, but with a special intent.
+``pplib`` provides a basic interface for these special arrays::
+
+ typedef struct {
+ ppnum lx, ly, rx, ry;
+ } pprect;
+
+This type is used only by helper functions - PDF parser is not aware of the rectangle type.
+To convert ``pparray`` to ``pprect``::
+
+ pprect * pparray_to_rect (pparray *array, pprect *rect); // returns rect or NULL
+
+In example::
+
+ pprect rect;
+ if (pparray_to_rect(array, &rect) != NULL)
+ ; // do something with rect
+
+To get some image bounding box::
+
+ pprect * ppdict_get_rect (ppdict *dict, const char *name, pprect *rect);
+ // eg. ppdict_get_rect(imagedict, "BBox", &rect)
+
+To get some page box::
+
+ pprect * ppdict_get_box (ppdict *dict, const char *name, pprect *rect);
+ // eg. ppdict_get_box(pagedict, "MediaBox", &rect)
+
+The later not only checks the pagedict, but also goes through parent page nodes.
+
+Transforms
+----------
+
+Transformations are given as 6-number arrays, but with a special intent.
+``pplib`` provides a basic interface for these special arrays::
+
+ typedef struct {
+ ppnum xx, xy, yx, yy, x, y;
+ } ppmatrix;
+
+This type is used only by helper functions - PDF parser is not aware of the matrix type.
+To convert ``pparray`` to ``ppmatrix``::
+
+ ppmatrix * pparray_to_matrix (pparray *array, ppmatrix *matrix);
+
+In example::
+
+ ppmatrix matrix;
+ if (pparray_to_matrix(array, &matrix) != NULL)
+ ; // do something with matrix
+
+To get the matrix from dict::
+
+ ppmatrix * ppdict_get_matrix (ppdict *dict, const char *name, ppmatrix *matrix);
+ // eg. ppdict_get_matrix(imagedict, "Matrix", &matrix)
+
+Errors handling
+---------------
+
+``pplib`` is not verbose, but might happen that it needs to log some error message, eg. when parsing
+of some PDF boject fails due to invalid offsets. By default, ``pplib`` prints the message to stdout, eg.::
+
+ invalid 123 0 R object at offset 123123
+
+To replace the default logger, you can provide your own::
+
+ void pplog_callback (pplogger_callback logger, void *alien);
+
+``pplogger_callback`` is a function::
+
+ void your_callback (const char *message, void *alien);
+
+In example, to redirect messages to stderr you may define a function::
+
+ void your_callback (const char *message, void *alien)
+ {
+ fprintf((FILE *)alien, "\nooops: %s\n", message);
+ }
+
+Then set the callback somewhere before loading documents::
+
+ pplog_callback(your_callback, stderr);
+
+(example 2 uses that).
+
+To set the default log messages prefix, eg. ``pplib:``, use::
+
+ int pplog_prefix (const char *prefix)
+
+Default is empty. The function succeeds if provided prefix is reasonably short (less then 32 bytes).
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/ppapi-2.x.rst b/Build/source/texk/web2c/luatexdir/luapplib/doc/ppapi-2.x.rst new file mode 100644 index 00000000000..250cd8fcd35 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/ppapi-2.x.rst @@ -0,0 +1,937 @@ +
+``pplib`` 2.x
+=============
+
+``pplib`` is a library for raw PDF access. It parses PDF documents and provides an interface to access document structures in C.
+
+C-API
+=====
+
+Types
+-----
+
+``pplib`` defines several C-types to represent PDF types:
+
+- ``ppbyte`` - char
+- ``ppint`` - signed integer (``int64_t``)
+- ``ppnum`` - real number (double)
+- ``ppname`` - PDF name
+- ``ppstring`` - PDF string
+- ``pparray`` - PDF array
+- ``ppdict`` - PDF dict
+- ``ppstream`` - PDF stream
+- ``ppref`` - PDF indirect reference
+- ``ppobj`` - a container of all above
+
+Among ``ppint`` and ``ppnum``, we also use ``ppuint`` - unsigned integer (machine word, alias to ``size_t``).
+
+Other API types:
+
+- ``ppdoc`` - PDF document
+- ``ppxref`` - cross-references table
+- ``ppcontext`` - ... later
+- ``pprect`` - rectangle
+- ``ppmatrix`` - matrix
+
+Integer and number are as simple types. Names and strings used to be aliases to ``char *``
+in ``pplib 1.x``, now they are structures; all related API functions operate on pointers.
+Other types (array, dict, stream, reference, object container, xref, doc) are C-structures,
+and you operate it their pointers. So when you declare a simple type variable you say::
+
+ ppuint u;
+ ppnum n;
+ ...
+
+And when you declare a compound type you operate on pointers::
+
+ ppobj *obj;
+ ppname *name;
+ ppstring *string;
+ pparray *array;
+ ppdict *dict;
+ ppstream *stream;
+ ppref *ref;
+ ppdoc *pdf;
+
+Most of those C-types are defined in library header ``ppapi.h`` (complete types). Some others are incomplete
+(eg. you can't say ``sizeof(ppdoc)`` or ``sizeof(ppxref)``). This is to avoid unnecesary dependencies in
+the header. The library itself uses ``pplib.h`` header but for auxilary applications including a standalone
+``ppapi.h`` header should be enough.
+
+``pplib`` was designed having **read-only** PDF access in mind. Even if some structure is completelly exposed,
+so that you can directly access its members, you should treat them as read-only. I don't make them ``const`` because
+then all variable declarations would need to be ``const``, which is annoying, and I'd need some trickery in the library
+internals to unconst. Besides, nothing is really const for C type casts.
+
+Object
+------
+
+A common container for all elementary PDF object types is ``ppobj`` structure. ``ppobj`` has a type identifier
+(integer) and union of values::
+
+ struct ppobj {
+ ppobjtp type;
+ union {
+ ppint integer;
+ ppnum number;
+ ppname *name;
+ ppstring *string;
+ pparray *array;
+ ppdict *dict;
+ ppstream *stream;
+ ppref *ref;
+ void *any;
+ };
+ };
+
+Object type is one of constants (enum)::
+
+ PPNONE
+ PPNULL
+ PPBOOL
+ PPINT
+ PPNUM
+ PPNAME
+ PPSTRING
+ PPARRAY
+ PPDICT
+ PPSTREAM
+ PPREF
+
+The type determines the structure member you're allowed to access::
+
+ ppobj *obj;
+ ...
+ switch (obj->type)
+ {
+ case PPNONE: // shouldn't actually happen, indicates some failure
+ break;
+ case PPNULL: // valid PDF null object, no value
+ break;
+ case PPBOOL: // do something with obj->integer (ppint), value 0 or 1
+ break;
+ case PPINT: // do something with obj->integer (ppint)
+ break;
+ case PPNUM: // do something with obj->number (ppnum)
+ break;
+ case PPNAME: // do something with obj->name (ppname *)
+ break;
+ case PPSTRING: // do something with obj->string (ppstring *)
+ break;
+ case PPARRAY: // do something with obj->array (pparray *)
+ break;
+ case PPDICT: // do something with obj->dict (ppdict *)
+ break;
+ case PPSTREAM: // do something with obj->stream (ppstream *)
+ break;
+ case PPREF: // do something with obj->ref (ppref *)
+ break;
+ }
+
+More often then not you know exactly what type of object value is expected, in which case
+you may use one of the following macros::
+
+ // returns 1 if o->type is PPNULL
+ int ppobj_get_null(o) \
+
+ // if o->type is PPBOOL, sets int v to 0 or 1 and returns 1, 0 otherwise
+ int ppobj_get_bool(o, v)
+
+ // if o->type is PPINT, sets ppint v and returns 1, 0 otherwise
+ int ppobj_get_int(o, v)
+
+ // if o->type is PPINT and >= 0, sets ppuint v and returns 1, 0 otherwise
+ int ppobj_get_uint(o, v)
+
+ // if o->type is PPNUM or PPINT, sets ppnum v and returns 1, 0 otherwise
+ int ppobj_get_num(o, v)
+
+ // if o->type is PPNAME returns the name, NULL otherwise
+ ppname * ppobj_get_name(o)
+
+ // if o->type is PPSTRING returns the string, NULL otherwise
+ ppstring * ppobj_get_string(o)
+
+ // if o->type is PPARRAY returns the array, NULL otherwise
+ pparray * ppobj_get_array(o)
+
+ // if o->type is PPDICT returns the dict, NULL otherwise
+ ppdict * ppobj_get_dict(o)
+
+ // if o->type is PPSTREAM returns the stream, NULL otherwise
+ ppstream * ppobj_get_stream(o)
+
+ // if o->type is PPREF returns the reference, NULL otherwise
+ ppref * ppobj_get_ref(o)
+
+Note the coercion from integer to real number, but not reverse. In practise, whenever you expect a real number,
+you should also handle integer (eg. '1' used instead of '1.0' is pretty common in PDF).
+
+It is a common case that the object is given as an indirect reference, but what you actually
+want is not the reference, but the object referred by it. Here is a helper for it::
+
+ // if o->type is PPREF, returns what the reference points, otherwise returns o
+ ppobj * ppobj_rget_obj(o)
+
+Also every ``ppobj_get_*`` macro has ``ppobj_rget_*`` counterpart that makes a check
+for the expected type, but if the object is PPREF, it jumps to the target object.
+So for example ``ppobj_rget_dict(obj)`` will return dict if ``obj`` is of type PPDICT
+or if it is of type PPREF and ``obj->ref`` hosts an object of type PPDICT.
+
+Names
+-----
+
+PDF names are represented as ``ppname`` pointer (``ppname`` used to be an alias to ``char *``, now it is a structure).
+To access the name data::
+
+ ppbyte * ppname_data(name) // name->data, bytes array
+
+For convenient use in C, names are ``'\0'`` terminated. But to get the length of name better always use
+``ppname_size()`` macro. ``ppname`` object knows its size, don't use ``strlen()``::
+
+ size_t ppname_size(ppname name); // name->size, the length of name in bytes
+
+In current implementation names are not hashed anyhow, so name-to-name comparison is not smarter than ``memcmp()``.
+Use macros::
+
+ int ppname_is(ppname name, "literal"); // to compare ppname with C-literal string
+ int ppname_eq(ppname name, ppname other); // to compare ppname with a different name
+
+If you use ``pplib`` to parse contents streams, you may need to distinguish names from operators
+(more precisely executable names). Names in PDF are preceeded by '/', executable names aren't. In both
+cases PDF parser will produce ``ppname`` but the result can be distingushed with::
+
+ int ppname_exec(ppname name); // macro, returns non-zero if the name is executable
+
+Names are kept in their raw form, with possible PDF specific escapes (in text below we call it **encoded** form).
+Leading '/' is omitted. One may need a decoded name, with no PDF escapes.
+A pair of functions provides a simple interface to switch between those two forms::
+
+ // these helpers rely on name->alterego member
+ ppname * ppname_decoded (ppname *name); // returns decoded (unescaped) form of the name
+ ppname * ppname_encoded (ppname *name); // returns encoded (escaped) form of the name
+ ppbyte * ppname_decoded_data (ppname *name);
+ ppbyte * ppname_encoded_data (ppname *name);
+
+In pretty most cases a PDF name contains only letters (no special characters, no escapes), so decoded and encoded forms are identical.
+In that case both functions simply return the argument. It is ok to call ``ppname_decoded()`` on already decoded form
+and ``ppname_encoded()`` on already encoded form. Both forms are produced by PDF objects parser, so accessing ``ppname`` alter ego
+in whatever direction needs no extra decoding or allocation costs (the cost is paid by parser).
+
+String
+------
+
+PDF strings have the same internal construction as names, so most of names description above applies to strings as well.
+``ppstring`` is a structure (used to be an alias to ``char *``). ``string->data`` is ``\0``-terminated c-array of ``ppbytes``.
+To get the data::
+
+ ppbyte * ppstring_data(ppstring *string); // string->data, macro
+
+To get the size of the string::
+
+ size_t ppstring_size(ppstring *string); // macro, returns the length of the string in bytes
+
+Strings are provided in their raw form, preserving PDF specific escapes, but with no
+``()`` or ``<>`` delims. To distinguish plain strings from hex strings::
+
+ int ppstring_hex(ppstring string); // macro, returns non zero if hex string
+
+Or if you prefer::
+
+ switch (ppstring_type(string))
+ {
+ case PPSTRING_PLAIN: // literal string, surrounded by ``(`` and ``)`` in PDF
+ break;
+ case PPSTRING_BASE16: // hex string, surrounded by ``<`` and ``>`` in PDF
+ break;
+ case PPSTRING_BASE85: // base85 string surrounded by ``<~`` and ``~>`` in PDF
+ break;
+ }
+
+The last is actually Postscript specific, not used in PDF, but I think it might appear in contents streams...
+No matter how the string is given in PDF (plain or hex), here are two functions to
+switch between encoded and decoded strings forms::
+
+ ppstring * ppstring_decoded (ppstring *string); // returns decoded string possibly with PDF escapes
+ ppstring * ppstring_encoded (ppstring *string); // returns encoded string with no PDF escapes
+ ppbyte * ppstring_decoded_data (ppstring *string);
+ ppbyte * ppstring_encoded_data (ppstring *string);
+
+For hex strings, encoded form contains hex digits, while decoded form contains arbitrary bytes (the result of hex decoding).
+Plain strings usually contains printable ASCII characters, but they might contain any binary data.
+As with names, objects parser produces both forms. The raw form with PDF escapes (or raw hex form) the main one.
+Eg. when you access ``obj->string`` you always get the encoded form. At any moment you can switch to its alter ego.
+
+No matter if the string is plain or hex, if its first two bytes (decoded) are UTF16 BOM, the string is unicode.
+``ppstring`` object *knows* it is unicode or not::
+
+ switch (ppstring_utf(string))
+ {
+ case PPSTRING_UTF16LE: // unicode string, utf16le
+ break;
+ case PPSTRING_UTF16BE: // unicode string, utf16be
+ break;
+ default: // no unicode
+ }
+
+Or simply::
+
+ if (ppstring_utf(string) != 0) {
+ // handle unicode string
+ }
+
+If the string is unicode, BOM remains the part of the string -- ``pplib`` parser does not strip it.
+Unicode or not, encoded or decoded, strings are always C-arrays of bytes and ``ppstring_size()``
+always returns the size in bytes.
+
+Array
+-----
+
+PDF arrays are represented as ``pparray`` type, which is C-array of ``ppobj`` structures.
+To get the size::
+
+ size_t pparray_size(pparray *array) // macro, returns the number of array items
+
+To get ``ppobj *`` at a given index::
+
+ ppobj * pparray_at(array, index) // macro, returns ppobj * (no index check)
+ ppobj * pparray_get(array, index) // macro, returns ppobj * or NULL (with index check)
+ ppobj * pparray_get_obj (pparray *array, size_t index); // function equiv to pparray_get()
+
+Iterating over array elements::
+
+ pparray *array;
+ size_t index, size;
+ ppobj *obj;
+ for (size = pparray_size(array), pparray_first(array, index, obj); index < size; pparray_next(index, obj))
+ {
+ // do something with index and obj
+ }
+
+There is no magic first/next macros, just iteration over pointers. One could also use something like::
+
+ for (index = 0, size = array->size; index < size; ++index)
+ {
+ obj = pparray_at(array, index);
+ // do something with index and obj
+ }
+
+When getting values from array and expecting a result of known type, use one of the following::
+
+ int pparray_get_bool (pparray *array, size_t index, int *v); // get boolean value
+ int pparray_get_int (pparray *array, size_t index, ppint *v); // get ppint value
+ int pparray_get_uint (pparray *array, size_t index, ppuint *v); // get ppuint value
+ int pparray_get_num (pparray *array, size_t index, ppnum *v); // get ppnum value
+ ppname * pparray_get_name (pparray *array, size_t index); // get ppname * value
+ ppstring * pparray_get_string (pparray *array, size_t index); // get ppstring * value
+ pparray * pparray_get_array (pparray *array, size_t index); // get pparray * value
+ ppdict * pparray_get_dict (pparray *array, size_t index); // get ppdict * value
+ ppref * pparray_get_ref (pparray *array, size_t index); // get ppref * value
+
+As with ``ppobj_get_*`` suite, numeric types getters set the value of a given type and returns 1, if the type matches.
+Otherwise sets nothing and returns 0. Other getters return the value if the type matches, or NULL.
+
+Every function from ``pparray_get_*`` suite have its ``pparray_rget_*`` counterpart
+that dereferences indirect objects (as explained for ``ppobj_rget_*`` getters). Note that
+there is no ``pparray_get_stream()`` function, as streams in PDF are always indirect
+(may only reside in ``ref->object.stream``). To get the stream from array use::
+
+ ppstream * pparray_rget_stream (pparray *array, size_t index);
+
+Dict
+----
+
+PDF dicts are represented as ``ppdict`` structure, which is C-array of ``ppobj`` with parallel
+C-array of ``ppname`` pointers. To get the size of a dict::
+
+ size_t ppdict_size(ppdict *dict) // macro, returns the number of key-val pairs
+
+To get the value at a given index (integer)::
+
+ ppobj * ppdict_at(ppdict *dict, index) // macro, no index bounds check
+
+To get the name (key) at a given index::
+
+ ppname * ppdict_key(ppdict *dict, index) // macro, no index bounds check
+
+To iterate over dict key-val pairs::
+
+ ppdict *dict;
+ ppname **pkey;
+ ppobj *obj;
+
+ for (ppdict_first(dict, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj))
+ {
+ // do something with *pkey and obj
+ }
+
+There is no magic in first/next macros, just iteration through keys and values lists pointers.
+For convenient iteration, a list of keys is terminated with NULL, so in the code above ``*pkey != NULL``
+is used as the loop condition. One may also iterate via indices::
+
+ ppdict *dict;
+ size_t index, size;
+ ppname *key;
+ ppobj *obj;
+ for (index = 0, size = ppdict_size(dict); index < size; ++index)
+ {
+ key = ppdict_key(dict, index);
+ obj = ppdict_at(dict, index);
+ // do something with key and obj
+ }
+
+To get the object associated with a given name, use one of the following::
+
+ ppobj * ppdict_get_obj (ppdict *dict, const char *name);
+ int ppdict_get_bool (ppdict *dict, const char *name, int *v);
+ int ppdict_get_int (ppdict *dict, const char *name, ppint *v);
+ int ppdict_get_uint (ppdict *dict, const char *name, ppuint *v);
+ int ppdict_get_num (ppdict *dict, const char *name, ppnum *v);
+ ppname ppdict_get_name (ppdict *dict, const char *name);
+ ppstring ppdict_get_string (ppdict *dict, const char *name);
+ pparray * ppdict_get_array (ppdict *dict, const char *name);
+ ppdict * ppdict_get_dict (ppdict *dict, const char *name);
+ ppref * ppdict_get_ref (ppdict *dict, const char *name);
+
+Note that all getters accepts ``const char *`` as key, so it is ok to say::
+
+ ppdict_rget_dict(dict, "Resources");
+
+(the most common use I guess). But to use ``ppname`` object as a key, one have to
+use data member::
+
+ ppdic_rget_dict(dict, name->data); // ppname *name
+
+Every ``ppdict_get_*`` getter has ``ppdict_rget_*`` counterpart that dereferences
+indirect objects if necessary. Note that there is no ``ppdict_get_stream()`` function,
+but there is::
+
+ ppstream * ppdict_rget_stream (ppdict *dict, const char *name);
+
+So far dicts comes with no names mapping, so by-name dict accessors perform a linear search
+through the keys list. PDF dicts are usually small.
+
+Stream
+------
+
+PDF streams are represented as ``ppstream`` objects. To get the stream dict::
+
+ ppdict * ppstream_dict(ppstream *stream) // macro
+
+To read the stream data::
+
+ uint8_t * ppstream_first (ppstream *stream, size_t *size, int decode);
+ uint8_t * ppstream_next (ppstream *stream, size_t *size);
+ void ppstream_done (ppstream *stream);
+
+Both ``first` and ``next`` functions return a chunk of stream data and sets the ``size`` of the chunk.
+``decode`` parameter tell the reader to decompress the stream (1) or return raw (0). A call to ``ppstream_next()``
+must be preceeded by ``ppstream_first()``. Once you're done with the stream, you have to call ``ppstream_done()``,
+no matter if the stream has been read to the end or not. The stream data iterator in use::
+
+ uint8_t *data;
+ size_t size;
+ ppstream *stream;
+ int decode = 1; // 1 - get decompressed, 0 - get raw
+
+ for (data = ppstream_first(stream, &size, decode); data != NULL; data = ppstream_next(stream, &size))
+ {
+ // do something with data and its size
+ }
+ ppstream_done(stream);
+
+Every subsequent iterator call invalidates the previous reader output, so you have to utilize the returned chunk
+of data just after you ot that. So the following is wrong::
+
+ data1 = ppstream_first(stream, &size, 1);
+ data2 = ppstream_next(stream, &size);
+ data3 = ppstream_next(stream, &size);
+ some_output(data1, size);
+ some_output(data2, size);
+
+The reader calls usually return the same pointer to internal buffer, just filled with a different data.
+``pplib`` allocates reasonably large buffer and fills that buffer on subsequent calls to the reader.
+
+If the source stream has no compression, using both ``decode == 1`` and ``decode == 0`` should give the same result.
+You can check if the stream is actually compressed with::
+
+ ppstream_compressed(stream) // macro, returns non zero if /Filter is present
+
+It might be necessary to load the entire stream data at once::
+
+ uint8_t * ppstream_all (ppstream *stream, size_t *size, int decode);
+
+If the initial buffer size is insufficient, it grows until the entire stream data is loaded. You must call
+``ppstream_done(stream)`` after using returned data.
+
+``ppstream_done()`` doesn't invalidate the stream object, it just closes its internal reader.
+The stream itself remains a valid object (eg. one can read it again if necessary),
+but the reader buffer is released. It is actually not freed but kept for future the reuse with that on some other stream,
+but you still need to mark it ready for reuse to avoid allocating a separate buffer for every stream you're going to read.
+
+Stream data readers will return ``NULL`` if you haven't close the previous reader process with ``ppstream_done()``. All below is wrong::
+
+ data1 = ppstream_all(stream, &size, 1);
+ data2 = ppstream_all(stream, &size, 1); // data2 == NULL
+ // or
+ data1 = ppstream_first(stream, &size, 1);
+ data2 = ppstream_first(stream, &size, 1); // data2 == NULL
+ // or
+ data1 = ppstream_first(stream, &size, 1);
+ data2 = ppstream_all(stream, &size, 1); // data2 == NULL
+
+To avoid unnecessary dependencies, ``pplib`` does not support image filters (``/DCT``, ``/JPX``, ``/JBIG``, ``/CCITT``).
+But it is ok to read the stream with ``decode`` set to 1 on such streams. ``pplib`` assumes that the image is the
+final/target stream form and just returns it as-is. Eg. in the case of JPEG (``/DCT`` filtered) image both calls should
+give the same results::
+
+ ppstream_all(jpegstream, &jpegsize, 0); // don't decode, return what's there
+ ppstream_all(jpegstream, &jpegsize, 1); // decode but found image filter, effectively the same
+
+A bit more about streams memory. As mentioned, ``pplib`` allocates buffers for stream readers. After ``ppstream_done()``,
+the stream no longer *owns* the buffer space. But the buffer may remain allocated, to be reused with future readers.
+``pplib`` keeps a pool of several buffers. This means, that when you use stream readers, ``pplib`` eats
+some memory (1MB or so) that is not freed, even if no streams are used. And even if you free all objects.
+If you suffer from this, you can optionally use a pair of functions::
+
+ void ppstream_init_buffers (void);
+ void ppstream_free_buffers (void);
+
+The first initializes buffers pool, unless done so far. Currently ``pplib`` cares of it before opening every stream reader,
+so it is not obligatory. The second frees a pool of buffers. The intended use is to call ``ppstream_init_buffers()`` once
+as kind of library initializer and to call ``ppstream_free_buffers()`` once, as the library finalizer.
+
+Filters
+-------
+
+``ppstream`` knows its filter(s) and keps it as ``stream->filter``::
+
+ // ppstream *stream;
+ ppstream_filter *info = &stream->filter;
+
+``ppstream_filter`` is the following structure::
+
+ typedef struct {
+ ppstreamtp *filters; // c-array of filter identifiers (enum integers)
+ ppdict **params; // c-array of ppdict pointers
+ size_t count; // number of filters, length of the arrays (typically 1)
+ } ppstream_filter;
+
+If ``count > 0`` then ``filters`` member is not NULL. Filters array keeps integer constants::
+
+ PPSTREAM_BASE16 /* /ASCIIHexDecode */
+ PPSTREAM_BASE85 /* /ASCII85Decode */
+ PPSTREAM_RUNLENGTH /* /RunLengthDecode */
+ PPSTREAM_FLATE /* /FlateDecode */
+ PPSTREAM_LZW /* /LZWDecode */
+ PPSTREAM_CCITT /* /CCITTFaxDecode */
+ PPSTREAM_DCT /* /DCTDecode */
+ PPSTREAM_JBIG2 /* /JBIG2Decode */
+ PPSTREAM_JPX /* /JPXDecode */
+ PPSTREAM_CRYPT /* /Crypt */
+
+Params array keeps corresponding filter parameters (``/DecodeParms``) if present. ``params`` member is not NULL
+if ``count > 0`` and the stream dict has ``/DecodeParms`` entry. Even if ``params`` is there,
+for every N-th filter, ``params[N]`` may be NULL (corresponding to PDF ``null``).
+
+``stream->filter`` keeps the source stream filter information, which may not correspond to the result of stream readers
+(``ppstream_first()``, ``ppstream_next()``, ``ppstream_all()``). The get the filters info relevant to the result from readers::
+
+ void ppstream_filter_info (ppstream *stream, ppstream_filter *info, int decode);
+
+The function fills ``ppstream_filter`` structure according to the expected result from stream readers (example 3 shows
+how to use it to reconstruct ``/Filter`` and ``/DecodeParms`` when copying the stream to some other PDF).
+
+To convert filter identifier (``ppstreamtp``) to a corresponding PDF filter name::
+
+ const char * ppstream_filter_name[];
+
+To covert ``ppname`` to filter identifier::
+
+ int ppstream_filter_type (ppname filtername, ppstreamtp *filtertype);
+ // returns 1 and sets filtertype if filtername is the proper filter name
+
+Additional information about the stream can be fetched from macros::
+
+ ppstream_compressed(stream) /* stream->flags & (PPSTREAM_FILTER|PPSTREAM_IMAGE) */
+ ppstream_filtered(stream) /* stream->flags & PPSTREAM_FILTER */
+ ppstream_image(stream) /* stream->flags * PPSTREAM_IMAGE */
+
+``stream->flags`` is a binary sum of the following::
+
+ PPSTREAM_FILTER /* set iff the stream filters list has one of: BASE16, BASE85, RUNLENGTH, FLATE, LZW */
+ PPSTREAM_IMAGE /* set iff the stream filters list has one of: CCITT, DCT, JBIG2, JPX */
+ PPSTREAM_ENCRYPTED /* set iff the stream is encrypted */
+ PPSTREAM_ENCRYPTED_OWN /* set iff the stream has own CRYPT filter */
+
+Note that ``PPSTREAM_COMPRESSED`` is not there any longer, use ``ppstream_compressed()`` instead.
+And there is some more, see ``ppapi.h``.
+
+Ref
+---
+
+Indirect objects are represented as ``ppref`` structure. To get the object that the
+reference refers to::
+
+ ppobj * ppref_obj(ppref *ref) // macro
+
+``ppref`` structure also keeps the reference number and version, a pointer to cross reference table it belongs
+to and others, but I guess you won't need anything but the referenced object. ``pplib`` parser resolves references
+on-fly. So if there is a dict with indirect objects::
+
+ <<
+ /Type /Page
+ /Resources 123 0 R
+ ...
+ >>
+
+the parser will produce ``ppdict`` with ``Resources`` key pointing the proper ``ppref *`` value.
+If you need more, access ``ppref`` members::
+
+ struct ppref {
+ ppobj object; // target object
+ ppuint number, version; // identifiers
+ size_t offset; // file offset (useless for you, may be zero for compressed objects)
+ ppuint length; // the length of the original object data
+ ppxref *xref; // cross reference table it belongs to
+ };
+
+
+XRef
+----
+
+Cross reference table is exposed as ``ppxref`` (incomplete type, you can only oprate on its pointer).
+To get top document xref::
+
+ ppxref * ppdoc_xref (ppdoc *pdf);
+
+To get previous (older) xref::
+
+ ppxref * ppxref_prev (ppxref *xref);
+
+To find an object of a given refnumber::
+
+ ppref * ppxref_find (ppxref *xref, ppuint refnumber);
+
+[Note: since pplib v0.98 in case of documents with incremental update, ``ppxref_find()`` returns
+the newest available version of a given object rather than the object in a given body.]
+
+PDF
+---
+
+PDF document is represented as ``ppdoc`` structure (incomplete type, you can only operate on its pointer).
+To load a document from file::
+
+ ppdoc * ppdoc_load (const char *filename);
+
+To load a document from file handle::
+
+ ppdoc * ppdoc_filehandle (FILE *file, int closefile); // closefile 1 to fclose() on end
+
+To load a document from memory data::
+
+ ppdoc * ppdoc_mem (const void *data, size_t size);
+
+The data is assumed to be a buffer allocated with ``malloc`` - it is freed when destroying ``ppdoc``.
+
+Both loaders returns ``NULL`` on failure.
+
+To free ``ppdoc`` and all objects it refers to::
+
+ void ppdoc_free (ppdoc *pdf);
+
+So far we haven't mention about any explicit object reclaimers. There are no dedicated ``free`` functions
+for other objects. You don't allocate or free objects yourself. ``ppdoc`` object is an owner of all
+beings it refers to. It also means that every object described so far is alive as long as the containing
+``ppdoc`` is alive.
+
+To access main PDF dicts::
+
+ ppdict * ppdoc_trailer(ppdoc *pdf); // returns top xref trailer dict
+ ppdict * ppdoc_catalog(ppdoc *pdf); // returns catalog referred from the trailer
+ ppdict * ppdoc_info(ppdoc *pdf); // returns info dict referred from the trailer
+
+To get the PDF version::
+
+ const char * ppdoc_version_string (ppdoc *pdf); // version string
+ int ppdoc_version_number (ppdoc *pdf, int *minor); // minor and major numbers
+
+To get the file size of the source PDF document::
+
+ size_t ppdoc_file_size (ppdoc *pdf);
+
+To get the number of objects in all xrefs::
+
+ ppuint ppdoc_objects (ppdoc *pdf);
+
+To get the approx usage of memory::
+
+ size_t ppdoc_memory (ppdoc *pdf, size_t *waste);
+
+Encryption
+----------
+
+``pplib`` handles encrypted (password protected) documents. If a document is encrypted, most of strings and streams are ciphered.
+In that form they are unreadable and rather useless, you can't even rewrite such strings/streams as-is to a different PDF output.
+It is a common practise to *protect* documents with an empty password. Such documents remain readable in Acrobat (just opens them without prompting
+for a password), but some features (eg. printing) may restricted by the application.
+
+When ``pplib`` detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, ``pplib`` proceeeds normally, providing
+an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, ``pplib`` gives
+a way to provide a password and proceed. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object wntries
+set to ``null``.
+
+After loading a document you should check encryption status with::
+
+ ppcrypt_status ppdoc_crypt_status (ppdoc *pdf);
+
+``ppcrypt_status`` (integer) may have the following values:
+
+ ``PPCRYPT_NONE`` - no encryption, go ahead
+ ``PPCRYPT_DONE`` - encryption present but password succeeded, go ahead
+ ``PPCRYPT_PASS`` - encryption present, need non-empty password
+ ``PPCRYPT_FAIL`` - invalid or unsupported encryption (eg. undocumented in pdf spec)
+
+If a password is needed, you can provide one with::
+
+ ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength,
+ const void *ownerpass, size_t ownerpasslength);
+
+Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough
+to know that having one of them is enough to decrypt the document. If you know the password, you probably mean
+``userpass``, in which case you should put ``NULL`` as ``ownerpass``. The function returns ``PPCRYPT_DONE`` if the password
+succeeds and the previous status otherwise. Your custom loader function may look like that::
+
+ ppdoc *pdf;
+ pdf = ppdoc_load("file.pdf");
+ if (pdf == NULL)
+ return NULL;
+ switch (ppdoc_crypt_status(pdf))
+ {
+ case PPCRYPT_NONE:
+ case PPCRYPT_DONE:
+ return pdf;
+ case PPCRYPT_PASS:
+ if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE ||
+ ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE)
+ return pdf;
+ printf("sorry, password needed\n");
+ ppdoc_free(pdf);
+ return NULL;
+ case PPCRYPT_FAIL:
+ printf("sorry, encryption failed\n");
+ ppdoc_free(pdf);
+ return NULL;
+ }
+
+[If you get ``PPCRYPT_FAIL`` it might mean *I failed*, so treat as a bug.]
+
+If you'd like to know what permissions are given/restricted to encrypted document::
+
+ ppint ppdoc_permissions (ppdoc *pdf);
+
+Returned value can be queried with the following binary flags (you can verify with Acrobat *File -> Properties -> Security* tab)::
+
+ PPDOC_ALLOW_PRINT // printing
+ PPDOC_ALLOW_MODIFY // filling form fields, signing, creating template pages
+ PPDOC_ALLOW_COPY // copying, copying for accessibility
+ PPDOC_ALLOW_ANNOTS // filling form fields, copying, signing
+ PPDOC_ALLOW_EXTRACT // contents copying for accessibility
+ PPDOC_ALLOW_ASSEMBLY // (no effect)
+ PPDOC_ALLOW_PRINT_HIRES // (no effect)
+
+``pplib`` does absolutelly nothing with permissions, it cares only to decrypt the document. As mentioned, encryption applies to strings
+and streams. ``pplib`` decrypt strings when parsing document objects, so the result you get is *normal* (not ciphered).
+Streams are decrypted whenever you access them. Even if you ask for a raw stream data, you'll get a raw (compressed) stream, but decrypted.
+So except the check to ``ppdoc_crypt_status()``, you shouldn't bother about encryption.
+
+In encrypted documents most of streams are encrypted. To check if a given stream is encrypted::
+
+ ppstream_encrypted(stream) // macro, returns non-zero if encrypted
+
+Encryption is independent from compression, don't confuse with ``ppstream_compressed()``
+
+Pages
+-----
+
+Several helpers to deal with pages. To get the number of pages::
+
+ ppuint ppdoc_page_count (ppdoc *pdf);
+
+To access the root pages tree node::
+
+ ppref * ppdoc_pages(ppdoc *pdf);
+
+To get the page reference at a given index::
+
+ ppref * ppdoc_page (ppdoc *pdf, ppuint index);
+
+``index`` is a page number. First page has number 1. For index out of bounds ``ppdoc_page()`` returns NULL.
+Iterating over pages using index from 1 to ``ppdoc_page_count()`` and calling ``ppdoc_page()`` on each iteration
+would be suboptimal. Here is a dedicted iterator for this::
+
+ ppref * ppdoc_first_page (ppdoc *pdf);
+ ppref * ppdoc_next_page (ppdoc *pdf);
+
+The iterator in use::
+
+ ppdoc *pdf;
+ ppref *ref;
+ ppdict *dict;
+ int pageno;
+
+ pdf = ppdoc_load("file.pdf");
+ for (ref = ppdoc_first_page(pdf), pageno = 1; ref != NULL; ref = ppdoc_next_page(pdf), ++pageno)
+ {
+ dict = ppref_obj(obj)->dict; // take for granted it is a dict
+ // do something with the page dict
+ }
+
+Functions related to pages return ``ppref *`` ensured to contain dict object, so you don't need sanity
+type checks here.
+
+Contents
+--------
+
+PDF page contents can be given as a stream or array of streams. Here is a convenience iterator over page
+contents streams::
+
+ ppstream * ppcontents_first (ppdict *dict);
+ ppstream * ppcontents_next (ppdict *dict, ppstream *stream);
+
+A complete example of contents stream parser use is given below (example 2).
+But before we get there, we need to introduce ``ppcontext`` object. Conceptually,
+``ppcontext`` is an owner (memory handler) of objects created on demand (beyond the ``ppdoc``).
+So far used only with contents stream parser, which might produce quite some data that we want
+to release just after used. To create a new context::
+
+ pcontext * ppcontext_new (void);
+
+It initializes a new context and its internal memory heap, taking about 64kB on start. After that,
+the context is ready to produce objects (contents parsing functions below). Once objects produced
+from a given context are no longer needed::
+
+ void ppcontext_done (ppcontext *context);
+
+It restores the context to its initial state, as after ``ppcontext_new()``. It means that the context
+is ready to produce another bunch of beings (in the example below, all objects from the next page contents).
+Once the context is not needed anymore::
+
+ void ppcontext_free (ppcontext *context);
+
+Now, contents stream parser functions take the context as an argument. Iterator form of contents stream parser
+that allows to process the contents operator by operator::
+
+ ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname);
+ ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname);
+
+Returned ``ppobj *`` is a pointer to operands list. ``*psize`` is the number of operands on stack.
+The operator itself is stored as ``*pname``.
+
+To parse the entire contents stream at once with no stop at every operator::
+
+ ppobj * ppcontents_parse (ppcontext *context, ppstream *stream, size_t *psize);
+
+Returns probably quite long list of all parsed objects (operands and operatos) in one piece.
+The number of objects is stored to ``*psize``.
+
+[Contents may contain so called inline images, that breaks a simple scheme of operands / operator syntax::
+
+ BI <keyval pairs> ID <binary image data> EI
+
+Contents parser treats this genuine triplet as a single piece, producing two operands (dict and string)
+followed by ``EI`` operator name.]
+
+Boxes
+-----
+
+Boxes (rectangles) in PDF are roughly 4-number arrays, but with a special intent.
+``pplib`` provides a basic interface for these special arrays::
+
+ typedef struct {
+ ppnum lx, ly, rx, ry;
+ } pprect;
+
+This type is used only by helper functions - PDF parser is not aware of the rectangle type.
+To convert ``pparray`` to ``pprect``::
+
+ pprect * pparray_to_rect (pparray *array, pprect *rect); // returns rect or NULL
+
+In example::
+
+ pprect rect;
+ if (pparray_to_rect(array, &rect) != NULL)
+ ; // do something with rect
+
+To get some image bounding box::
+
+ pprect * ppdict_get_rect (ppdict *dict, const char *name, pprect *rect);
+ // eg. ppdict_get_rect(imagedict, "BBox", &rect)
+
+To get some page box::
+
+ pprect * ppdict_get_box (ppdict *dict, const char *name, pprect *rect);
+ // eg. ppdict_get_box(pagedict, "MediaBox", &rect)
+
+The later not only checks the pagedict, but also goes through parent page nodes.
+
+Transforms
+----------
+
+Transformations are given as 6-number arrays, but with a special intent.
+``pplib`` provides a basic interface for these special arrays::
+
+ typedef struct {
+ ppnum xx, xy, yx, yy, x, y;
+ } ppmatrix;
+
+This type is used only by helper functions - PDF parser is not aware of the matrix type.
+To convert ``pparray`` to ``ppmatrix``::
+
+ ppmatrix * pparray_to_matrix (pparray *array, ppmatrix *matrix);
+
+In example::
+
+ ppmatrix matrix;
+ if (pparray_to_matrix(array, &matrix) != NULL)
+ ; // do something with matrix
+
+To get the matrix from dict::
+
+ ppmatrix * ppdict_get_matrix (ppdict *dict, const char *name, ppmatrix *matrix);
+ // eg. ppdict_get_matrix(imagedict, "Matrix", &matrix)
+
+Errors handling
+---------------
+
+``pplib`` is not verbose, but might happen that it needs to log some error message, eg. when parsing
+of some PDF boject fails due to invalid offsets. By default, ``pplib`` prints the message to stdout, eg.::
+
+ invalid 123 0 R object at offset 123123
+
+To replace the default logger, you can provide your own::
+
+ void pplog_callback (pplogger_callback logger, void *alien);
+
+``pplogger_callback`` is a function::
+
+ void your_callback (const char *message, void *alien);
+
+In example, to redirect messages to stderr you may define a function::
+
+ void your_callback (const char *message, void *alien)
+ {
+ fprintf((FILE *)alien, "\nooops: %s\n", message);
+ }
+
+Then set the callback somewhere before loading documents::
+
+ pplog_callback(your_callback, stderr);
+
+(example 2 uses that).
+
+To set the default log messages prefix, eg. ``pplib:``, use::
+
+ int pplog_prefix (const char *prefix)
+
+Default is empty. The function succeeds if provided prefix is reasonably short (less then 32 bytes).
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/ppcode.rst b/Build/source/texk/web2c/luatexdir/luapplib/doc/ppcode.rst new file mode 100644 index 00000000000..ebe92465d80 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/ppcode.rst @@ -0,0 +1,101 @@ +Examples
+========
+
+Example 1
+---------
+
+.. literalinclude:: ../src/pptest1.c
+
+Example 2
+---------
+
+.. literalinclude:: ../src/pptest2.c
+
+Example 3
+---------
+
+.. literalinclude:: ../src/pptest3.c
+
+ppapi.h
+-------
+
+.. literalinclude:: ../src/ppapi.h
+
+
+Changes
+=======
+
+v0.97
+-----
+First release integrated with luatex sources, plus portability changes from Luigi.
+
+v0.98
+-----
+Changed references resolving in case of incremental updates; tech notes ppxref_find() in ppxref.c.
+
+v0.99
+-----
+Fixed streams handling; null characters should NOT be gobbled after "stream" keyword
+
+v1.00
+-----
+Fixed streams handling (Luigi); object streams updated before other streams
+Revised streams handling, ppstream API extended
+
+v1.01
+-----
+Fixed names handling (thanks Hans); digits after '#' weren't skipped
+
+v1.02
+-----
+Fixed page finder (thanks Luigi)
+
+v1.03
+-----
+Fixed TIFF predictor (thanks folks)
+
+v1.04
+-----
+Fixed TIFF predictor for ARM
+
+v1.05
+-----
+Attempt to fix parsing inline images crap
+
+v2.00
+-----
+Deep rework on allocators.
+Deep rework on strings and names.
+
+v2.01
+-----
+Fixed invalid stream buffer handling; ``iof_discard()`` no longer reclaims the source (``filter->next``) filter.
+Sanity alignment adjustments in ``iof_heap``.
+
+v2.02
+-----
+Fixed incorrect encoding of strings alterego with octal escaping, thanks Luigi.
+On Hans request added ``ppdoc_filehandle()`` function and ``ppdoc_file()`` macro for loading ppdoc from ``FILE *``.
+
+v2.03
+-----
+Fixed alloc/free of ``ppdoc`` heap; ``ppdoc`` is now mallocated, no longer taken from its own heap. Again, thanks Luigi.
+Fixed warnings about dereferencing type-puned pointers, and some others.
+
+v2.04
+-----
+Byte lookups for names/strings loaders are now int8_t, as char might be signed.
+ppdoc_first_page() / ppdoc_next_page() iterator now handles a case when /Kids array is empty.
+Fixed generating keys for encrypted streams; ppstring_internal() returns the string of the proper size.
+More stream tests in pptest3.c.
+Some rework on md5 and sha2.
+
+v2.05
+-----
+uint8_t instead of ppbyte in internals; ppbyte intent is "the most natural 8-bit integer", so it is 'char',
+but internally we almost always need uint8_t (char may be signed or not..)
+
+TODO
+====
+- external streams (egzotic)
+
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/pplib.rst b/Build/source/texk/web2c/luatexdir/luapplib/doc/pplib.rst new file mode 100644 index 00000000000..763dc79cf62 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/pplib.rst @@ -0,0 +1,15 @@ +.. pplib documentation master file, created by
+ sphinx-quickstart on Thu Jun 07 14:23:51 2018.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+pplib
+=====
+
+.. toctree::
+ :maxdepth: 2
+
+ ppnew
+ ppapi-2.x
+ ppapi-1.x
+ ppcode
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/doc/ppnew.rst b/Build/source/texk/web2c/luatexdir/luapplib/doc/ppnew.rst new file mode 100644 index 00000000000..4a0a3b42887 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/doc/ppnew.rst @@ -0,0 +1,103 @@ +
+1.x vs 2.x
+==========
+
+Allocation
+----------
+
+Allocation mechanisms has been revised. All objects are still allocated from a private storage (called heap),
+but now the heap serves properly aligned memory chunks. Implementation of the heap is (hopefully) platform
+independent, so all ``ARM_COMPLIANT`` checks has been removed. Some details work differently on 32/64-bit
+machines, this distinction seems inevitable. Allocation related code has been moved to ``util/utilmem*.c`` files.
+
+[There are actually 3 different allocators - **heap**, **stock**, and **pool** - each of which has 4 variants
+for 1, 2, 4 and 8 bytes alignment. So far ``pplib`` uses only the **heap**, but I want to have this part
+in a single place for a while. More notes about allocators in ``utilmemallc.h``.]
+
+``pplib`` uses two heaps:
+
+* bytes heap - providing 2-bytes aligned memory chunks for byte data
+* structures heap - providing 8-bytes aligned chunks for all structures
+
+2-bytes alignment of byte data is caused by implementation details / limits, ``pplib`` doesn't make a use of it
+(could be unaligned as well). All the structures are stored in 8-bytes aligned chunks on both 32 and 64-bit machines
+(in some structures we use ``double`` and ``int64_t``, which generally needs 8-bytes).
+
+Strings And Names
+-----------------
+
+So far, both ``ppname`` and ``ppstring`` were aliases to ``char *`` with an extra structure hidden just below
+the data address. The idea was to make a string or name usable whenever chars array can, at the cost of some
+pointers trickery. Both names and strings keep an information about pdf-encoded data, as well as plain bytes data.
+I implemented this feature once ``pplib 1.0`` was almost done, and to avoid a revolution, I made that with yet
+another trick. This all was dirty and caused lots of alignment issues.
+
+Now ``ppstring`` and ``ppname`` are **structures**, keeping data and size members, pretty much like ``pparray``::
+
+ struct ppname {
+ ppbyte *data;
+ size_t size;
+ ppname *alterego;
+ int flags;
+ };
+
+ struct ppstring {
+ ppbyte *data;
+ size_t size;
+ ppstring *alterego;
+ int flags;
+ };
+
+Data member is a pointer to (2-bytes aligned) bytes array -- ``ppbyte *``. ``ppbyte`` is an alias to ``char``.
+``pplib`` makes no assumptions about ``ppbyte`` signedness. [I'd prefer to have ``uint8_t``, but better
+keep that in sync with ``ppdict_get_*`` suite, which accepts ``char *``. Using ``"string literals"``
+with ``ppdict_get`` function is the most common case, I guess.]
+
+``ppname_size()`` and ``ppstring_size() `` now have
+trivial ``ppname_data()`` and ``ppstring_data()`` counterparts::
+
+ #define ppname_size(name) ((name)->size)
+ #define ppname_data(name) ((name)->data)
+
+ #define ppstring_size(string) ((string)->size)
+ #define ppstring_data(string) ((string)->data)
+
+Switching between encoded / decoded variants is made via explicit ``alterego`` member. If encoded and decoded forms
+are identical, then ``self->alfterego == self`` (never NULL). Helper functions for that::
+
+ PPAPI ppname * ppname_decoded (ppname *name);
+ PPAPI ppname * ppname_encoded (ppname *name);
+
+ PPAPI ppbyte * ppname_decoded_data (ppname *name);
+ PPAPI ppbyte * ppname_encoded_data (ppname *name);
+
+ PPAPI ppstring * ppstring_decoded (ppstring *string);
+ PPAPI ppstring * ppstring_encoded (ppstring *string);
+
+ PPAPI ppbyte * ppstring_decoded_data (ppstring *string);
+ PPAPI ppbyte * ppstring_encoded_data (ppstring *string);
+
+Since ``ppname`` and ``ppstring`` are now structures, all API functions returning name/string or taking name/string
+as an argument, now take **a pointer to name/string**. Watch out for ``ppdict_get_*`` functions suite. They still accept
+``const char *`` key as an argument, but ``ppname`` type can no longer be used there::
+
+ ppname key;
+ ppdict_get_something(dict, key); // wrong
+ ppdict_get_something(dict, key.data); // ok
+
+ ppname *pkey;
+ ppdict_get_something(dict, (const char *)pkey); // wrong
+ ppdict_get_something(dict, pkey->data); // ok
+
+Consequently, functions / macros that used pointer to ``ppname`` (``ppdict_first()`` / ``ppdict_next()``),
+now needs ``ppname **pname``.
+
+Cleanups
+--------
+
+Some of unused utils were removed. There is still some code in utils part that is not used by the library,
+but I need this tollbox in many other places and don't want to maintain two versions.
+
+Some unification in integer types; ``size_t`` seems to be the best choice for and integer representing machine
+word (``unsigned long`` is not long enough on windows), less utils dependencies, less compiler warnings.
+
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_sources/ppcode.rst.txt b/Build/source/texk/web2c/luatexdir/luapplib/html/_sources/ppcode.rst.txt deleted file mode 100644 index 06f5659c6b0..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_sources/ppcode.rst.txt +++ /dev/null @@ -1,64 +0,0 @@ -Examples
-========
-
-Example 1
----------
-
-.. literalinclude:: ../pptest1.c
-
-Example 2
----------
-
-.. literalinclude:: ../pptest2.c
-
-Example 3
----------
-
-.. literalinclude:: ../pptest3.c
-
-ppapi.h
--------
-
-.. literalinclude:: ../ppapi.h
-
-
-Changes
-=======
-
-v0.97
------
-First release integrated with luatex sources, plus portability changes from Luigi.
-
-v0.98
------
-Changed references resolving in case of incremental updates; tech notes ppxref_find() in ppxref.c.
-
-v0.99
------
-Fixed streams handling; null characters should NOT be gobbled after "stream" keyword
-
-v1.00
------
-Fixed streams handling (Luigi); object streams updated before other streams
-Revised streams handling, ppstream API extended
-
-v1.01
------
-Fixed names handling (thanks Hans); digits after '#' weren't skipped
-
-v1.02
------
-Fixed page finder (thanks Luigi)
-
-v1.03
------
-Fixed TIFF predictor (thanks folks)
-
-v1.04
------
-Fixed TIFF predictor for ARM
-
-TODO
-====
-- external streams (egzotic)
-
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/documentation_options.js b/Build/source/texk/web2c/luatexdir/luapplib/html/_static/documentation_options.js deleted file mode 100644 index fb47b84aaec..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/_static/documentation_options.js +++ /dev/null @@ -1,9 +0,0 @@ -var DOCUMENTATION_OPTIONS = { - URL_ROOT: '', - VERSION: '0.1', - LANGUAGE: 'None', - COLLAPSE_INDEX: false, - FILE_SUFFIX: '.html', - HAS_SOURCE: true, - SOURCELINK_SUFFIX: '.txt' -};
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/objects.inv b/Build/source/texk/web2c/luatexdir/luapplib/html/objects.inv deleted file mode 100644 index 75c713d28fd..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/objects.inv +++ /dev/null @@ -1,6 +0,0 @@ -# Sphinx inventory version 2 -# Project: pplib -# Version: -# The remainder of this file is compressed using zlib. -xÚmÎ1 -Ã0@Ñݧðèš½C‡B 'P,áäXÄ)¤·ol¥ƒ¡›øzZãŠtزãÈ0[w³áªÃ²'¶:š”ñ”û-?3¾™®Ø0ûÆkP(Âq>…ÏH=©EÍý€$LÅ4Ü«3(r¦l~éÓ¦â¥û ™/T»T
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/html/searchindex.js b/Build/source/texk/web2c/luatexdir/luapplib/html/searchindex.js deleted file mode 100644 index df9ec39cdf3..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/html/searchindex.js +++ /dev/null @@ -1 +0,0 @@ -Search.setIndex({docnames:["ppapi","ppcode","pplib"],envversion:52,filenames:["ppapi.rst","ppcode.rst","pplib.rst"],objects:{},objnames:{},objtypes:{},terms:{"1mb":0,"2fkb":1,"2fmb":1,"64kb":0,"boolean":0,"break":[0,1],"byte":0,"case":[0,1],"char":[0,1],"const":[0,1],"default":[0,1],"enum":[0,1],"final":0,"function":0,"int":[0,1],"long":[0,1],"new":0,"null":[0,1],"return":[0,1],"short":0,"static":1,"switch":[0,1],"void":[0,1],"while":0,And:0,But:0,For:0,NOT:1,One:0,Such:0,The:0,Then:0,There:0,Use:0,__aarch64__:[],__arm:[],__arm__:[],__arm_arch:[],__sun:[],__svr4:[],_ppname:1,_ppname_ghost:1,_ppstring:1,_ppstring_ghost:1,about:0,abov:0,absolutelli:0,accept:0,access:[0,1],accessor:0,accord:0,acrobat:[0,1],actual:0,addit:0,after:[0,1],again:0,ahead:0,alia:0,alias:[],alien:[0,1],aliv:0,all:0,alloc:0,allow:0,alreadi:0,also:0,alter:0,alwai:0,among:0,ani:[0,1],annoi:0,anoth:0,anyhow:0,anymor:0,anyth:0,api:[1,2],app:0,appear:0,appli:0,applic:0,approach:0,approx:0,arbitrari:0,aren:0,argc:1,argument:0,argv0:1,argv:1,arm:1,arm_compli:1,arrai:[1,2],artbox:1,ascii85decod:0,ascii:0,asciihexdecod:0,ask:0,assert:1,associ:0,assum:0,auxilari:0,avail:0,avoid:0,awar:0,base16:0,base85:0,basic:0,bbox:0,becaus:0,been:0,befor:[0,1],beings:0,belong:0,below:0,besid:0,better:0,between:0,beyond:0,binari:0,bit:0,bleedbox:1,bodi:0,boject:0,bom:0,both:0,bother:0,bound:0,box:[1,2],box_info:1,buffer:[0,1],bug:0,build:0,bunch:0,call:0,callback:0,can:[0,1],captur:[],care:0,cast:0,catalog:0,ccitt:0,ccittfaxdecod:0,chang:2,charact:[0,1],check:0,chunk:0,cipher:0,clear:0,close:0,code:0,coercion:0,come:0,common:0,compar:0,comparison:0,complet:0,completelli:0,compound:0,compress:[0,1],conceptu:0,condit:0,confus:0,consid:0,constant:0,construct:0,contain:0,content:[1,2],context:[0,1],continu:1,conveni:0,convert:0,copi:[0,1],correspond:0,cost:0,could:0,count:[0,1],counterpart:0,covert:0,creat:[0,1],creator:1,cropbox:1,cross:0,crypt:[0,1],crypt_info:1,cryptkei:1,cstr:0,cstring:0,current:0,custom:0,data1:0,data2:0,data3:0,data:[0,1],dct:0,dctdecod:0,deal:0,debug:[],declar:0,decod:[0,1],decodeparm:[0,1],decompress:[0,1],decrypt:0,dedic:0,dedict:0,defin:[0,1],delim:0,demand:0,depend:0,depth:[],derefer:0,describ:0,descript:0,design:0,destroi:0,detect:0,determin:0,dict:[1,2],differ:0,digit:[0,1],direct:0,directli:0,distinguish:0,distingush:0,doc:1,document:0,doe:0,doesn:0,don:0,done:[0,1],doubl:[0,1],due:0,dummi:[0,1],each:0,eat:0,effect:[0,1],ego:0,egzot:1,element:0,elementari:0,els:1,empti:[0,1],encod:0,encount:[],encrypt:[1,2],end:0,endif:1,enough:0,ensur:0,entir:0,entri:0,equiv:0,error:2,escap:0,even:0,everi:0,exactli:0,exampl:[0,2],except:0,execut:0,expect:0,explain:0,explicit:0,expos:0,extend:[0,1],extens:0,extern:1,extra:0,fail:[0,1],failur:0,far:0,fast:0,fault:0,fclose:1,featur:0,fetch:0,field:[0,1],file1:1,file2:1,file:[0,1],filenam:[0,1],filepath:1,files:1,filespec:1,fill:[0,1],filter:[1,2],filternam:[0,1],filtertyp:[0,1],find:0,finder:1,first:[0,1],fix:1,flag:[0,1],flate:0,flatedecod:0,fly:0,folk:1,follow:0,fopen:1,forbidden:0,form:[0,1],found:0,fprintf:[0,1],free:0,freed:0,from:[0,1],futur:0,fwrite:1,genuin:0,get:0,get_file_nam:1,getter:0,give:0,given:0,gobbl:1,goe:0,going:0,grant:0,grow:0,guess:0,gust:1,han:1,handl:[1,2],handler:0,happen:[0,1],has:0,hash:0,have:0,haven:0,header:0,heap:0,helper:0,here:0,hex:0,hide:0,host:0,how:0,howev:0,hundr:0,ident:0,identifi:0,iff:0,ifndef:1,imag:[0,1],imagedict:0,implement:0,includ:[0,1],incomplet:0,increment:[0,1],independ:0,index:[0,1],indic:0,indirect:0,info:[0,1],inform:0,initi:0,inlin:0,input:1,instead:0,insuffici:0,int64_t:[0,1],integ:[0,1],integr:1,intend:0,intent:0,interfac:0,intern:0,introduc:0,invalid:[0,1],item:[0,1],iter:0,its:0,itself:0,jackowski:1,jbig2:0,jbig2decod:0,jbig:0,jpeg:0,jpegsiz:0,jpegstream:0,jpx:0,jpxdecod:0,jump:0,just:0,keep:0,kei:[0,1],kep:0,kept:0,keyval:0,keyword:1,kind:0,know:0,known:0,larg:0,last:[0,1],later:0,lead:0,length:[0,1],less:0,letter:0,librari:0,like:0,linear:0,list:0,liter:0,load:[0,1],loader:0,log:0,log_callback:1,logger:[0,1],longer:0,look:0,lookup:0,loop:0,luatex:1,luigi:1,lzw:0,lzwdecod:0,machin:[0,1],macro:0,magic:0,mai:0,main:[0,1],major:0,make:0,malloc:0,map:0,mark:0,match:0,matrix:[0,1],matter:0,mean:0,mechan:[],mediabox:[0,1],member:0,memcmp:[0,1],memori:0,memus:1,memwast:1,mention:0,messag:[0,1],might:0,mind:0,minor:[0,1],moment:0,more:0,most:0,must:0,name:[1,2],necessari:0,need:[0,1],newest:0,next:0,node:0,non:0,none:1,nonempti:1,nooop:[0,1],normal:0,note:[0,1],noth:0,now:[0,1],number:[0,1],numer:0,obj:[0,1],object:[1,2],obligatori:0,obscur:0,offset:[0,1],often:0,older:0,omit:0,onc:0,one:0,onli:[0,1],open:[0,1],oper:[0,1],operand:0,operato:0,oprat:0,option:0,org:1,origin:0,other:[0,1],otherwis:0,out:[0,1],outdir:1,outnam:1,output:0,over:0,own:0,owner:0,ownerpass:[0,1],ownerpasslength:[0,1],page:[1,2],pagecount:1,pagedict:[0,1],pageno:[0,1],pageref:1,pair:0,parallel:0,param:[0,1],paramet:0,parent:0,pars:[0,1],parser:[0,1],part:0,password:[0,1],path:1,pcontext:0,pdf:[1,2],perfectli:0,perform:0,permiss:[0,1],piec:0,pkei:[0,1],plain:[0,1],plu:1,pname:[0,1],point:0,pointer:0,pool:0,portabl:1,possibl:0,postscript:[0,1],pp_api_h:1,ppapi:[0,2],pparrai:[0,1],pparray_align:1,pparray_at:[0,1],pparray_first:[0,1],pparray_get:[0,1],pparray_get_:0,pparray_get_arrai:[0,1],pparray_get_bool:[0,1],pparray_get_dict:[0,1],pparray_get_int:[0,1],pparray_get_nam:[0,1],pparray_get_num:[0,1],pparray_get_obj:[0,1],pparray_get_ref:[0,1],pparray_get_str:[0,1],pparray_get_stream:[0,1],pparray_get_uint:[0,1],pparray_next:[0,1],pparray_rget_:0,pparray_rget_arrai:1,pparray_rget_bool:1,pparray_rget_dict:1,pparray_rget_int:1,pparray_rget_nam:1,pparray_rget_num:1,pparray_rget_obj:1,pparray_rget_ref:1,pparray_rget_str:1,pparray_rget_stream:[0,1],pparray_rget_uint:1,pparray_s:[0,1],pparray_to_matrix:[0,1],pparray_to_rect:[0,1],ppbool:[0,1],ppconf:1,ppcontents_first:[0,1],ppcontents_first_op:[0,1],ppcontents_next:[0,1],ppcontents_next_op:[0,1],ppcontents_pars:[0,1],ppcontext:[0,1],ppcontext_don:[0,1],ppcontext_fre:[0,1],ppcontext_new:[0,1],ppcrypt_don:[0,1],ppcrypt_fail:[0,1],ppcrypt_non:[0,1],ppcrypt_pass:[0,1],ppcrypt_statu:[0,1],ppdef:1,ppdic_rget_dict:0,ppdict:[0,1],ppdict_align:1,ppdict_at:[0,1],ppdict_first:[0,1],ppdict_get_:0,ppdict_get_arrai:[0,1],ppdict_get_bool:[0,1],ppdict_get_box:[0,1],ppdict_get_dict:[0,1],ppdict_get_int:[0,1],ppdict_get_matrix:[0,1],ppdict_get_nam:[0,1],ppdict_get_num:[0,1],ppdict_get_obj:[0,1],ppdict_get_rect:[0,1],ppdict_get_ref:[0,1],ppdict_get_str:[0,1],ppdict_get_stream:[0,1],ppdict_get_uint:[0,1],ppdict_kei:[0,1],ppdict_next:[0,1],ppdict_rget_:0,ppdict_rget_arrai:1,ppdict_rget_bool:1,ppdict_rget_dict:[0,1],ppdict_rget_int:1,ppdict_rget_nam:1,ppdict_rget_num:1,ppdict_rget_obj:1,ppdict_rget_ref:1,ppdict_rget_str:1,ppdict_rget_stream:[0,1],ppdict_rget_uint:1,ppdict_siz:[0,1],ppdoc:[0,1],ppdoc_allow_annot:[0,1],ppdoc_allow_assembl:[0,1],ppdoc_allow_copi:[0,1],ppdoc_allow_extract:[0,1],ppdoc_allow_modifi:[0,1],ppdoc_allow_print:[0,1],ppdoc_allow_print_hir:[0,1],ppdoc_catalog:[0,1],ppdoc_crypt_pass:[0,1],ppdoc_crypt_statu:[0,1],ppdoc_file_s:[0,1],ppdoc_first_pag:[0,1],ppdoc_fre:[0,1],ppdoc_info:[0,1],ppdoc_load:[0,1],ppdoc_mem:[0,1],ppdoc_memori:[0,1],ppdoc_next_pag:[0,1],ppdoc_object:[0,1],ppdoc_pag:[0,1],ppdoc_page_count:[0,1],ppdoc_permiss:[0,1],ppdoc_trail:[0,1],ppdoc_version_numb:[0,1],ppdoc_version_str:[0,1],ppdoc_xref:[0,1],ppint:[0,1],pplib:1,pplib_author:1,pplib_vers:1,pplog_callback:[0,1],pplog_prefix:[0,1],pplogger_callback:[0,1],ppmatrix:[0,1],ppmess:[],ppname:[0,1],ppname_decod:[0,1],ppname_encod:[0,1],ppname_eq:[0,1],ppname_exec:[0,1],ppname_i:[0,1],ppname_s:[0,1],ppnone:[0,1],ppnull:[0,1],ppnum:[0,1],ppobj:[0,1],ppobj_get_:0,ppobj_get_arrai:[0,1],ppobj_get_bool:[0,1],ppobj_get_bool_valu:1,ppobj_get_dict:[0,1],ppobj_get_int:[0,1],ppobj_get_int_valu:1,ppobj_get_nam:[0,1],ppobj_get_nul:[0,1],ppobj_get_num:[0,1],ppobj_get_num_valu:1,ppobj_get_ref:[0,1],ppobj_get_str:[0,1],ppobj_get_stream:[0,1],ppobj_get_uint:[0,1],ppobj_kind:1,ppobj_rget_:0,ppobj_rget_arrai:1,ppobj_rget_bool:1,ppobj_rget_dict:[0,1],ppobj_rget_int:1,ppobj_rget_nam:1,ppobj_rget_nul:1,ppobj_rget_num:1,ppobj_rget_obj:[0,1],ppobj_rget_ref:1,ppobj_rget_str:1,ppobj_rget_stream:1,ppobj_rget_uint:1,ppobjtp:[0,1],pprect:[0,1],ppref:[0,1],ppref_obj:[0,1],ppsizef:1,ppstream:[0,1],ppstream_al:[0,1],ppstream_base16:[0,1],ppstream_base85:[0,1],ppstream_ccitt:[0,1],ppstream_compress:[0,1],ppstream_crypt:[0,1],ppstream_dct:[0,1],ppstream_dict:[0,1],ppstream_don:[0,1],ppstream_encrypt:[0,1],ppstream_encrypted_a:1,ppstream_encrypted_own:[0,1],ppstream_encrypted_rc4:1,ppstream_filt:[0,1],ppstream_filter_info:[0,1],ppstream_filter_nam:[0,1],ppstream_filter_typ:[0,1],ppstream_first:[0,1],ppstream_flat:[0,1],ppstream_free_buff:[0,1],ppstream_imag:[0,1],ppstream_init_buff:[0,1],ppstream_jbig2:[0,1],ppstream_jpx:[0,1],ppstream_lzw:[0,1],ppstream_next:[0,1],ppstream_not_support:1,ppstream_runlength:[0,1],ppstreamtp:[0,1],ppstring:[0,1],ppstring_base16:[0,1],ppstring_base85:[0,1],ppstring_decod:[0,1],ppstring_encod:[0,1],ppstring_exec:1,ppstring_hex:[0,1],ppstring_plain:[0,1],ppstring_siz:[0,1],ppstring_typ:[0,1],ppstring_utf16b:[0,1],ppstring_utf16l:[0,1],ppstring_utf:[0,1],ppuint:[0,1],ppuintf:1,ppxref:[0,1],ppxref_catalog:1,ppxref_find:[0,1],ppxref_info:1,ppxref_pag:1,ppxref_prev:[0,1],ppxref_trail:1,ppxsec:1,practis:0,preceed:0,precis:0,predictor:1,prefer:0,prefix:[0,1],present:0,preserv:0,pretend:0,pretti:0,previou:0,print:[0,1],print_info:1,print_result_filt:1,print_stream_info:1,printabl:0,printf:[0,1],probabl:0,problem:[],proce:0,procee:0,process:0,produc:[0,1],prompt:0,proper:0,properti:[0,1],protect:[0,1],provid:0,psize:[0,1],put:0,queri:0,quit:0,rather:0,raw:0,read:0,readabl:0,reader:0,readi:0,real:0,realli:0,reason:0,reclaim:0,reconstruct:0,rect:[0,1],rectangl:0,redirect:0,ref:[1,2],refer:[0,1],referenc:0,refnum:1,refnumb:[0,1],relat:0,releas:[0,1],relev:0,remain:0,replac:0,repres:0,resolv:[0,1],resourc:0,restor:0,restrict:0,result:0,reus:0,revers:0,revis:1,rewrit:0,root:0,roughli:0,runlength:0,runlengthdecod:0,sai:0,same:0,saniti:0,scheme:0,search:0,second:0,sect:1,secur:[0,1],see:0,segment:0,sens:0,separ:0,set:0,sever:0,should:[0,1],shouldn:[0,1],show:0,sign:[0,1],simpl:0,simpli:0,sinc:0,singl:0,size:[0,1],size_t:[0,1],sizenum:1,sizeof:[0,1],skip:1,small:0,smarter:0,some:0,some_output:0,somehow:[],someth:0,somewher:0,soon:0,sorri:[0,1],sourc:[0,1],space:0,spec:0,special:0,specif:0,sprintf:1,stack:0,standalon:0,start:0,stat:[],state:0,statu:0,stddef:1,stderr:[0,1],stdint:1,stdio:1,stdout:0,still:0,stop:0,store:0,stream:[1,2],string:[1,2],strip:0,strlen:0,struct:[0,1],structur:0,style:0,suboptim:0,subsequ:0,succe:0,succeed:0,suffer:0,suit:0,sum:0,support:0,surround:0,syntax:0,tab:[0,1],tabl:0,take:0,target:0,tech:1,tell:0,templat:[0,1],termin:0,termini:0,text:0,than:0,thank:1,thei:0,them:0,thi:[0,1],think:0,those:0,though:0,through:0,tiff:1,todo:2,top:0,trailer:0,transform:[1,2],treat:0,tree:0,tri:0,trickeri:0,trimbox:1,triplet:0,two:0,type:[1,2],typedef:[0,1],typic:0,uint8_t:[0,1],uncompress:1,unconst:0,undocu:0,unescap:0,unicod:0,union:[0,1],unless:0,unnecesari:0,unnecessari:0,unread:0,unsign:[0,1],unsupport:0,until:0,updat:[0,1],usag:[0,1],use:0,used:0,useless:0,user:[],userpass:[0,1],userpasslength:[0,1],uses:0,using:0,usual:0,utf16:0,utf16b:0,utf16l:0,util:0,val:0,valid:0,valu:0,variabl:0,verbos:0,verifi:0,version:[0,1],via:0,wai:0,want:0,wast:[0,1],well:0,weren:[0,1],what:0,whatev:0,when:[0,1],whenev:0,which:0,without:0,wntri:0,won:0,word:[0,1],would:0,write:1,wrong:0,xref:[1,2],xsec:1,yes:0,you:0,your:0,your_callback:0,yourself:0,zero:0},titles:["<code class=\"docutils literal notranslate\"><span class=\"pre\">pplib</span></code>","Examples","pplib"],titleterms:{api:0,arrai:0,box:0,chang:1,content:0,dict:0,encrypt:0,error:0,exampl:1,filter:0,handl:0,name:0,object:0,page:0,pdf:0,ppapi:1,pplib:[0,2],ref:0,stream:0,string:0,todo:1,transform:0,type:0,xref:0}})
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppcrypt.c.orig b/Build/source/texk/web2c/luatexdir/luapplib/ppcrypt.c.orig deleted file mode 100644 index 4428a1ccf08..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppcrypt.c.orig +++ /dev/null @@ -1,628 +0,0 @@ - -#include "utilmd5.h" -#include "utilsha.h" - -#include "pplib.h" - -/* crypt struct */ - -#define CRYPT_AES (1<<0) -#define CRYPT_RC4 (1<<1) -#define CRYPT_MD (1<<2) -#define CRYPT_NOMD (1<<3) - -static ppcrypt * ppcrypt_create (ppheap **pheap) -{ - ppcrypt *crypt; - crypt = ppheap_take(pheap, sizeof(ppcrypt)); - memset(crypt, 0, sizeof(ppcrypt)); - return crypt; -} - -static int ppcrypt_type (ppcrypt *crypt, ppname cryptname, ppuint *length, int *cryptflags) -{ - ppdict *filterdict; - ppname filtertype; - int cryptmd = 0, default256 = 0; - - if (crypt->map == NULL || (filterdict = ppdict_rget_dict(crypt->map, cryptname)) == NULL) - return 0; - if ((filtertype = ppdict_get_name(filterdict, "CFM")) == NULL) - return 0; - *cryptflags = 0; - if (ppname_is(filtertype, "V2")) - *cryptflags |= CRYPT_RC4; - else if (ppname_is(filtertype, "AESV2")) - *cryptflags |= CRYPT_AES; - else if (ppname_is(filtertype, "AESV3")) - *cryptflags |= CRYPT_AES, default256 = 1; - else - return 0; - /* pdf spec page. 134: /Length is said to be optional bit-length of the key, but it seems to be a mistake, as Acrobat - produces /Length key with bytes lengths, opposite to /Length key of the main encrypt dict. */ - if (length != NULL) - if (!ppdict_get_uint(filterdict, "Length", length)) - *length = (*cryptflags & CRYPT_RC4) ? 5 : (default256 ? 32 : 16); - /* one of metadata flags is set iff there is an explicit EncryptMetadata key */ - if (ppdict_get_bool(filterdict, "EncryptMetadata", &cryptmd)) - *cryptflags |= (cryptmd ? CRYPT_MD : CRYPT_NOMD); - return 1; -} - -static const uint8_t padding_string[] = { - 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, - 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A -}; - -static void ppcrypt_set_userpass (ppcrypt *crypt, const void *userpass, size_t userpasslength) -{ - crypt->userpasslength = userpasslength > 32 ? 32 : userpasslength; - memcpy(crypt->userpass, userpass, crypt->userpasslength); - memcpy(crypt->userpass + crypt->userpasslength, padding_string, 32 - crypt->userpasslength); - crypt->flags |= PPCRYPT_USER_PASSWORD; -} - -static void ppcrypt_set_ownerpass (ppcrypt *crypt, const void *ownerpass, size_t ownerpasslength) -{ - crypt->ownerpasslength = ownerpasslength > 32 ? 32 : ownerpasslength; - memcpy(crypt->ownerpass, ownerpass, crypt->ownerpasslength); - memcpy(crypt->ownerpass + crypt->ownerpasslength, padding_string, 32 - crypt->ownerpasslength); - crypt->flags |= PPCRYPT_OWNER_PASSWORD; -} - -/* retrieving user password from owner password and owner key (variant < 5) */ - -static void ppcrypt_retrieve_userpass (ppcrypt *crypt, const void *ownerkey, size_t ownerkeysize) -{ - uint8_t temp[16], rc4key[32], rc4key2[32]; - uint8_t i; - ppuint k; - - md5init(); - md5add(crypt->ownerpass, 32); - md5put(rc4key); - if (crypt->algorithm_revision >= 3) - { - for (i = 0; i < 50; ++i) - { - md5(rc4key, 16, temp); - memcpy(rc4key, temp, 16); - } - } - rc4_decode_data(ownerkey, ownerkeysize, crypt->userpass, rc4key, crypt->filekeylength); - if (crypt->algorithm_revision >= 3) - { - for (i = 1; i <= 19; ++i) - { - for (k = 0; k < crypt->filekeylength; ++k) - rc4key2[k] = rc4key[k] ^ i; - rc4_decode_data(crypt->userpass, 32, crypt->userpass, rc4key2, crypt->filekeylength); - } - } - //crypt->userpasslength = 32; - for (crypt->userpasslength = 0; crypt->userpasslength < 32; ++crypt->userpasslength) - if (memcmp(&crypt->userpass[crypt->userpasslength], padding_string, 32 - crypt->userpasslength) == 0) - break; - crypt->flags |= PPCRYPT_USER_PASSWORD; -} - -/* generating file key; pdf spec p. 125 */ - -static void ppcrypt_filekey (ppcrypt *crypt, const void *ownerkey, size_t ownerkeysize, const void *id, size_t idsize) -{ - uint32_t p; - uint8_t permissions[4], temp[16]; - int i; - - md5init(); - md5add(crypt->userpass, 32); - md5add(ownerkey, ownerkeysize); - p = (uint32_t)crypt->permissions; - permissions[0] = get_byte1(p); - permissions[1] = get_byte2(p); - permissions[2] = get_byte3(p); - permissions[3] = get_byte4(p); - md5add(permissions, 4); - md5add(id, idsize); - if (crypt->algorithm_revision >= 4 && (crypt->flags & PPCRYPT_NO_METADATA)) - md5add("\xFF\xFF\xFF\xFF", 4); - md5put(crypt->filekey); - if (crypt->algorithm_revision >= 3) - { - for (i = 0; i < 50; ++i) - { - md5(crypt->filekey, (size_t)crypt->filekeylength, temp); - memcpy(crypt->filekey, temp, 16); - } - } -} - -/* generating userkey for comparison with /U; requires a general file key and id; pdf spec page 126-127 */ - -static void ppcrypt_userkey (ppcrypt *crypt, const void *id, size_t idsize, uint8_t *password_hash) -{ - uint8_t rc4key2[32]; - uint8_t i; - ppuint k; - - if (crypt->algorithm_revision <= 2) - { - rc4_encode_data(padding_string, 32, password_hash, crypt->filekey, crypt->filekeylength); - } - else - { - md5init(); - md5add(padding_string, 32); - md5add(id, idsize); - md5put(password_hash); - rc4_encode_data(password_hash, 16, password_hash, crypt->filekey, crypt->filekeylength); - for (i = 1; i <= 19; ++i) - { - for (k = 0; k < crypt->filekeylength; ++k) - rc4key2[k] = crypt->filekey[k] ^ i; - rc4_encode_data(password_hash, 16, password_hash, rc4key2, crypt->filekeylength); - } - for (i = 16; i < 32; ++i) - password_hash[i] = password_hash[i - 16] ^ i; /* arbitrary 16-bytes padding */ - } -} - -/* validating /Perms key (pdf 1.7, /V 5 /R 5 crypt) */ - -static const uint8_t nulliv[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* AES-256 initialization vector */ - -static ppcrypt_status ppcrypt_authenticate_perms (ppcrypt *crypt, ppstring perms) -{ /* decode /Perms string overriding crypt setup (should match anyway) */ - uint8_t permsdata[16]; - //int64_t p; - //int i; - - aes_decode_data(perms, ppstring_size(perms), permsdata, crypt->filekey, crypt->filekeylength, nulliv, AES_NULL_PADDING); - - if (permsdata[9] != 'a' || permsdata[10] != 'd' || permsdata[11] != 'b') - return PPCRYPT_FAIL; - - // do not update permissions flags; they seem to be different inside crypt string - //for (p = 0, i = 0; i < 8; ++i) - // p = p + (permsdata[i] << (i << 3)); /* low order bytes first */ - //crypt->permissions = (ppint)(int32_t)(p & 0x00000000FFFFFFFFLL); /* unset bits 33..64, treat as 32-bit signed int */ - - if (permsdata[8] == 'T') - crypt->flags &= ~PPCRYPT_NO_METADATA; - else if (permsdata[8] == 'F') - crypt->flags |= PPCRYPT_NO_METADATA; - - return PPCRYPT_DONE; -} - -ppcrypt_status ppdoc_crypt_init (ppdoc *pdf, const void *userpass, size_t userpasslength, const void *ownerpass, size_t ownerpasslength) -{ - ppcrypt *crypt; - ppdict *trailer, *encrypt; - ppobj *obj; - ppname name, *pkey; - ppstring userkey, ownerkey, userkey_e = NULL, ownerkey_e = NULL; - size_t hashlength; - pparray *idarray; - ppstring id = NULL, perms = NULL; - int cryptflags, encryptmd; - size_t strkeylength, stmkeylength; - - uint8_t password_hash[32]; /* /U and /O are 48 bytes strings for AES-256, but here we use only 32 */ - uint8_t *validation_salt, *key_salt; - - /* Every xref could theoretically have a separate encryption info. Not clarified in pdf spec but it seems that the top - level xref encryption info is the one to be applied to all objects in all xrefs, including older. */ - trailer = ppxref_trailer(pdf->xref); - if ((obj = ppdict_get_obj(trailer, "Encrypt")) == NULL) - return PPCRYPT_NONE; - /* Typically this is all done early, before loading body, so if /Encrypt is indirect reference, it points nothing. We have to load it here. */ - obj = ppobj_preloaded(pdf, obj); - if (obj->type != PPDICT) - return PPCRYPT_FAIL; - encrypt = obj->dict; - for (ppdict_first(encrypt, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj)) - (void)ppobj_preloaded(pdf, obj); - - if ((name = ppdict_get_name(encrypt, "Filter")) != NULL && !ppname_is(name, "Standard")) - return PPCRYPT_FAIL; - - if ((crypt = pdf->crypt) == NULL) - crypt = pdf->crypt = ppcrypt_create(&pdf->heap); - if (!ppdict_get_uint(encrypt, "V", &crypt->algorithm_variant)) - crypt->algorithm_variant = 0; - if (crypt->algorithm_variant < 1 || crypt->algorithm_variant > 5) - return PPCRYPT_FAIL; - if (!ppdict_get_uint(encrypt, "R", &crypt->algorithm_revision)) - return PPCRYPT_FAIL; - if (crypt->algorithm_revision >= 3) - crypt->flags |= PPCRYPT_OBSCURITY; - if (!ppdict_get_int(encrypt, "P", &crypt->permissions)) - return PPCRYPT_FAIL; - if ((userkey = ppdict_get_string(encrypt, "U")) == NULL || (ownerkey = ppdict_get_string(encrypt, "O")) == NULL) - return PPCRYPT_FAIL; - userkey = ppstring_decoded(userkey); - ownerkey = ppstring_decoded(ownerkey); - /* for some reason acrobat pads /O and /U to 127 bytes with NULL, so we don't check the exact length but ensure the minimal */ - hashlength = crypt->algorithm_variant < 5 ? 32 : 48; - if (ppstring_size(userkey) < hashlength || ppstring_size(ownerkey) < hashlength) - return PPCRYPT_FAIL; - if (crypt->algorithm_variant < 5) - { // get first string from /ID (must not be ref) - if ((idarray = ppdict_get_array(trailer, "ID")) == NULL || (id = pparray_get_string(idarray, 0)) == NULL) - return PPCRYPT_FAIL; - id = ppstring_decoded(id); - } - else - { - if ((userkey_e = ppdict_get_string(encrypt, "UE")) == NULL || (ownerkey_e = ppdict_get_string(encrypt, "OE")) == NULL) - return PPCRYPT_FAIL; - userkey_e = ppstring_decoded(userkey_e); - ownerkey_e = ppstring_decoded(ownerkey_e); - if (ppstring_size(userkey_e) < 32 || ppstring_size(ownerkey_e) < 32) - return PPCRYPT_FAIL; - if ((perms = ppdict_get_string(encrypt, "Perms")) == NULL) - return PPCRYPT_FAIL; - perms = ppstring_decoded(perms); - if (ppstring_size(perms) != 16) - return PPCRYPT_FAIL; - } - - switch (crypt->algorithm_revision) - { - case 1: - crypt->filekeylength = 5; - crypt->flags |= PPCRYPT_RC4; - break; - case 2: case 3: - if (ppdict_get_uint(encrypt, "Length", &crypt->filekeylength)) - crypt->filekeylength >>= 3; /* 40..256 bits, 5..32 bytes*/ - else - crypt->filekeylength = 5; /* 40 bits, 5 bytes */ - crypt->flags |= PPCRYPT_RC4; - break; - case 4: case 5: - if ((crypt->map = ppdict_rget_dict(encrypt, "CF")) == NULL) - return PPCRYPT_FAIL; - for (ppdict_first(crypt->map, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj)) - (void)ppobj_preloaded(pdf, obj); - /* /EncryptMetadata relevant only for version >=4, may be also provided in crypt filter dictionary; which takes a precedence then? - we assume that if there is an explicit EncryptMetadata key, it overrides main encrypt dict flag or default flag (the default is true, - meaning that Metadata stream is encrypted as others) */ - if (ppdict_get_bool(encrypt, "EncryptMetadata", &encryptmd) && !encryptmd) - crypt->flags |= PPCRYPT_NO_METADATA; - - strkeylength = stmkeylength = 0; - /* streams filter */ - if ((name = ppdict_get_name(encrypt, "StmF")) != NULL && ppcrypt_type(crypt, name, &stmkeylength, &cryptflags)) - { - if (cryptflags & CRYPT_AES) - crypt->flags |= PPCRYPT_STREAM_AES; - else if (cryptflags & CRYPT_RC4) - crypt->flags |= PPCRYPT_STREAM_RC4; - if (cryptflags & CRYPT_NOMD) - crypt->flags |= PPCRYPT_NO_METADATA; - else if (cryptflags & CRYPT_MD) - crypt->flags &= ~PPCRYPT_NO_METADATA; - } /* else identity */ - /* strings filter */ - if ((name = ppdict_get_name(encrypt, "StrF")) != NULL && ppcrypt_type(crypt, name, &strkeylength, &cryptflags)) - { - if (cryptflags & CRYPT_AES) - crypt->flags |= PPCRYPT_STRING_AES; - else if (cryptflags & CRYPT_RC4) - crypt->flags |= PPCRYPT_STRING_RC4; - } /* else identity */ - - /* /Length of encrypt dict is irrelevant here, theoretically every crypt filter may have own length... It means that we should - actually keep a different file key for streams and strings. But it leads to nonsense, as /U and /O entries refers to a single - keylength, without a distinction for strings/streams. So we have to assume /Length is consistent. To expose the limitation: */ - if ((crypt->flags & PPCRYPT_STREAM) && (crypt->flags & PPCRYPT_STRING)) - if (strkeylength != stmkeylength) - return PPCRYPT_FAIL; - crypt->filekeylength = stmkeylength ? stmkeylength : strkeylength; - if ((crypt->flags & PPCRYPT_STREAM) || (crypt->flags & PPCRYPT_STRING)) - if (crypt->filekeylength == 0) - return PPCRYPT_FAIL; - break; - default: - return PPCRYPT_FAIL; - } - - /* password */ - - if (userpass != NULL) - { - ppcrypt_set_userpass(crypt, userpass, userpasslength); - } - else if (ownerpass != NULL) - { - if (crypt->algorithm_variant < 5) // fetch user password from owner password - ppcrypt_retrieve_userpass(crypt, ownerkey, ppstring_size(ownerkey)); - else // open the document using owner password - ppcrypt_set_ownerpass(crypt, ownerpass, ownerpasslength); - } - else - { - return PPCRYPT_FAIL; - } - - if (crypt->algorithm_variant < 5) - { /* authenticate by comparing a generated vs present /U entry; depending on variant 16 or 32 bytes to compare */ - ppcrypt_filekey(crypt, ownerkey, ppstring_size(ownerkey), id, ppstring_size(id)); - ppcrypt_userkey(crypt, id, ppstring_size(id), password_hash); /* needs file key so comes after key generation */ - if (memcmp(userkey, password_hash, (crypt->algorithm_revision >= 3 ? 16 : 32)) == 0) - return PPCRYPT_DONE; - return PPCRYPT_PASS; - } - if (crypt->flags & PPCRYPT_USER_PASSWORD) - { - validation_salt = (uint8_t *)userkey + 32; - key_salt = validation_salt + 8; - sha256init(); - sha256add(crypt->userpass, crypt->userpasslength); - sha256add(validation_salt, 8); - sha256put(password_hash); - if (memcmp(userkey, password_hash, 32) != 0) - return PPCRYPT_PASS; - sha256init(); - sha256add(crypt->userpass, crypt->userpasslength); - sha256add(key_salt, 8); - sha256put(password_hash); - aes_decode_data(userkey_e, 32, crypt->filekey, password_hash, 32, nulliv, AES_NULL_PADDING); - return ppcrypt_authenticate_perms(crypt, perms); - } - if (crypt->flags & PPCRYPT_OWNER_PASSWORD) - { - validation_salt = (uint8_t *)ownerkey + 32; - key_salt = validation_salt + 8; - sha256init(); - sha256add(crypt->ownerpass, crypt->ownerpasslength); - sha256add(validation_salt, 8); - sha256add(userkey, 48); - sha256put(password_hash); - if (memcmp(ownerkey, password_hash, 32) != 0) - return PPCRYPT_PASS; - sha256init(); - sha256add(crypt->ownerpass, crypt->ownerpasslength); - sha256add(key_salt, 8); - sha256add(userkey, 48); - sha256put(password_hash); - aes_decode_data(ownerkey_e, 32, crypt->filekey, password_hash, 32, nulliv, AES_NULL_PADDING); - return ppcrypt_authenticate_perms(crypt, perms); - } - return PPCRYPT_FAIL; // should never get here -} - -/* decrypting strings */ - -/* -Since strings are generally rare, but might occur in mass (name trees). We generate decryption key when needed. -All strings within the same reference are crypted with the same key. Both RC4 and AES algorithms expands -the crypt key in some way and the result of expansion is the same for the same crypt key. Instead of recreating -the ky for every string, we backup the initial decryption state. -*/ - -static void ppcrypt_strkey (ppcrypt *crypt, ppref *ref, int aes) -{ - if (crypt->cryptkeylength > 0) - { /* crypt key already generated, just reinitialize crypt states */ - if (aes) - { /* aes codecs that works on c-strings do not modify aes_state flags at all, so we actually don't need to revitalize the state, - we only rewrite an initialization vector, which is modified during crypt procedure */ - } - else - { /* rc4 crypt map is modified during crypt procedure, so here we reinitialize rc4 bytes map */ - rc4_map_restore(&crypt->rc4state, &crypt->rc4copy); - } - return; - } - - if (crypt->algorithm_variant < 5) - { - crypt->filekey[crypt->filekeylength + 0] = get_byte1(ref->number); - crypt->filekey[crypt->filekeylength + 1] = get_byte2(ref->number); - crypt->filekey[crypt->filekeylength + 2] = get_byte3(ref->number); - crypt->filekey[crypt->filekeylength + 3] = get_byte1(ref->version); - crypt->filekey[crypt->filekeylength + 4] = get_byte2(ref->version); - - if (aes) - { - crypt->filekey[crypt->filekeylength + 5] = 0x73; - crypt->filekey[crypt->filekeylength + 6] = 0x41; - crypt->filekey[crypt->filekeylength + 7] = 0x6C; - crypt->filekey[crypt->filekeylength + 8] = 0x54; - } - - md5(crypt->filekey, crypt->filekeylength + (aes ? 9 : 5), crypt->cryptkey); - crypt->cryptkeylength = crypt->filekeylength + 5 >= 16 ? 16 : crypt->filekeylength + 5; - } - else - { - memcpy(crypt->cryptkey, crypt->filekey, 32); - crypt->cryptkeylength = 32; - } - - if (aes) - { - aes_decode_initialize(&crypt->aesstate, &crypt->aeskeyblock, crypt->cryptkey, crypt->cryptkeylength, NULL); - aes_pdf_mode(&crypt->aesstate); - } - else - { - rc4_state_initialize(&crypt->rc4state, &crypt->rc4map, crypt->cryptkey, crypt->cryptkeylength); - rc4_map_save(&crypt->rc4state, &crypt->rc4copy); - } -} - -int ppstring_decrypt (ppcrypt *crypt, const void *input, size_t size, void *output, size_t *newsize) -{ - int aes, rc4; - aes = crypt->flags & PPCRYPT_STRING_AES; - rc4 = crypt->flags & PPCRYPT_STRING_RC4; - if (aes || rc4) - { - ppcrypt_strkey(crypt, crypt->ref, aes); - if (aes) - *newsize = aes_decode_state_data(&crypt->aesstate, input, size, output); - else // if (rc4) - *newsize = rc4_decode_state_data(&crypt->rc4state, input, size, output); - return 1; - } - return 0; // identity crypt -} - -/* decrypting streams */ - -/* -Streams are decrypted everytime when accessing the stream data. We need to be able to get or make -the key for decryption as long as the stream is alive. And to get the key we need the reference -number and version, plus document crypt info. First thought was to keep the reference to which -the stream belongs; stream->ref and accessing the crypt info stream->ref->xref->pdf->crypt. -It would be ok as long as absolutelly nothing happens with ref and crypt. At some point pplib -may drift into rewriting support, which would imply ref/xref/crypt/pdf structures modifications. -So I feel better with generating a crypt key for every stream in encrypted document, paying a cost -of md5() for all streams, not necessarily those actually read. - -Key generation is the same as for strings, but different for distinct encryption methods (rc4 vs aes). -Since streams and strings might theoretically be encrypted with different filters. No reason to cacche -decryption state here. -*/ - -static ppstring ppcrypt_stmkey (ppcrypt *crypt, ppref *ref, int aes, ppheap **pheap) -{ - ppstring cryptkeystring; - //if (crypt->cryptkeylength > 0) - // return; - - if (crypt->algorithm_variant < 5) - { - crypt->filekey[crypt->filekeylength + 0] = get_byte1(ref->number); - crypt->filekey[crypt->filekeylength + 1] = get_byte2(ref->number); - crypt->filekey[crypt->filekeylength + 2] = get_byte3(ref->number); - crypt->filekey[crypt->filekeylength + 3] = get_byte1(ref->version); - crypt->filekey[crypt->filekeylength + 4] = get_byte2(ref->version); - - if (aes) - { - crypt->filekey[crypt->filekeylength + 5] = 0x73; - crypt->filekey[crypt->filekeylength + 6] = 0x41; - crypt->filekey[crypt->filekeylength + 7] = 0x6C; - crypt->filekey[crypt->filekeylength + 8] = 0x54; - } - - md5(crypt->filekey, crypt->filekeylength + (aes ? 9 : 5), crypt->cryptkey); - crypt->cryptkeylength = crypt->filekeylength + 5 >= 16 ? 16 : crypt->filekeylength + 5; // how about 256bits AES?? - } - else - { // we could actually generate this string once, but.. aes itself is way more expensive that we can earn here - memcpy(crypt->cryptkey, crypt->filekey, 32); // just for the record - crypt->cryptkeylength = 32; - } - cryptkeystring = ppstring_internal(crypt->cryptkey, crypt->cryptkeylength, pheap); - return ppstring_decoded(cryptkeystring); -} - -void ppstream_info (ppstream *stream, ppdoc *pdf) -{ // just after the stream creation - ppdict *dict; - ppobj *fobj, *pobj; - pparray *farray; - ppname fname, owncryptfilter, tname; - ppcrypt *crypt; - ppref *ref; - size_t i; - int owncrypt, cflags; - - dict = stream->dict; - ppdict_rget_uint(dict, "Length", &stream->length); - - if ((fobj = ppdict_get_obj(dict, "Filter")) != NULL) - { - fobj = ppobj_preloaded(pdf, fobj); - switch (fobj->type) - { - case PPNAME: - stream->flags |= PPSTREAM_COMPRESSED; - break; - case PPARRAY: - if (fobj->array->size > 0) - stream->flags |= PPSTREAM_COMPRESSED; - break; - default: - break; - } - } - if ((crypt = pdf->crypt) == NULL || (ref = crypt->ref) == NULL) - return; - owncrypt = 0; - owncryptfilter = NULL; - if (fobj != NULL) - { - if ((pobj = ppdict_get_obj(dict, "DecodeParms")) != NULL) - pobj = ppobj_preloaded(pdf, pobj); - switch (fobj->type) - { - case PPNAME: - if (ppname_is(fobj->name, "Crypt")) - { - owncrypt = 1; - if (pobj != NULL && pobj->type == PPDICT) // /Type /CryptFilterDecodeParms - owncryptfilter = ppdict_get_name(pobj->dict, "Name"); - } - break; - case PPARRAY: - farray = fobj->array; - for (i = 0; i < farray->size; ++i) - { - if ((fname = pparray_get_name(farray, i)) != NULL && ppname_is(fname, "Crypt")) - { - owncrypt = 1; - if (pobj != NULL && pobj->type == PPARRAY && (pobj = pparray_get_obj(pobj->array, i)) != NULL) - { - pobj = ppobj_preloaded(pdf, pobj); - if (pobj != NULL && pobj->type == PPDICT) // /Type /CryptFilterDecodeParms - owncryptfilter = ppdict_get_name(pobj->dict, "Name"); - } - break; - } - } - break; - default: - break; - } - } - - if (owncrypt) - { - stream->flags |= PPSTREAM_ENCRYPTED_OWN; - /* Seems a common habit to use just /Crypt filter name with no params, which defaults to /Identity. - A real example with uncompressed metadata: <</Filter[/Crypt]/Length 4217/Subtype/XML/Type/Metadata>> */ - if (owncryptfilter != NULL && !ppname_is(owncryptfilter, "Identity")) - { - if (crypt->map != NULL && ppcrypt_type(crypt, owncryptfilter, NULL, &cflags)) - { - if (cflags & CRYPT_AES) - stream->flags |= PPSTREAM_ENCRYPTED_AES; - else if (cflags & CRYPT_RC4) - stream->flags |= PPSTREAM_ENCRYPTED_RC4; - } - } - } - else - { - if ((crypt->flags & PPCRYPT_NO_METADATA) && (tname = ppdict_get_name(dict, "Type")) != NULL && ppname_is(tname, "Metadata")) - ; /* special treatment of metadata stream; we assume that explicit /Filter /Crypt setup overrides document level setup of EncryptMetadata. */ - else - { - if (crypt->flags & PPCRYPT_STREAM_RC4) - stream->flags |= PPSTREAM_ENCRYPTED_RC4; - else if (crypt->flags & PPCRYPT_STREAM_AES) - stream->flags |= PPSTREAM_ENCRYPTED_AES; - } - } - - /* finally, if the stream is encrypted with non-identity crypt (implicit or explicit), make and save the crypt key */ - if (stream->flags & PPSTREAM_ENCRYPTED) - stream->cryptkey = ppcrypt_stmkey(crypt, ref, ((stream->flags & PPSTREAM_ENCRYPTED_AES) != 0), &pdf->heap); -} diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppheap.c b/Build/source/texk/web2c/luatexdir/luapplib/ppheap.c deleted file mode 100644 index 112d88ca97e..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppheap.c +++ /dev/null @@ -1,435 +0,0 @@ - -#include "pplib.h" - -#define PPHEAP_BUFFER 0xFFFF -#define PPHEAP_WASTE 0x00FF - -#define ppheap_head(heap) ((uint8_t *)((heap) + 1)) - - -#if ARM_COMPLIANT -# define PPHEAP_ARCH_ARM -# define PPHEAP_NEED_ALIGNMENT -#endif - -#if defined(__sparc) -# define PPHEAP_NEED_ALIGNMENT -#endif - -#ifdef PPHEAP_NEED_ALIGNMENT -/* Tests has shown that long double seems to work: */ -/* for 32bit aligned_data has algn: 64 as ppxref and ppref, */ -/* the other algns divide algn: 64, so it's ok.*/ -/* Hopefully it's ok for aarch64 too */ - -/* These data are stored in ppheap.c.001t.tu */ -/* made with gcc -fdump-tree-all-fdump-tree-all */ - - -/* @2586 identifier_node strg: ppxref lngt: 6 */ -/* @2565 record_type name: @2586 size: @679 algn: 64 */ -/* tag : struct flds: @2587 */ - - -/* @2672 identifier_node strg: ppxsec lngt: 6 */ -/* @2648 type_decl name: @2672 type: @2623 scpe: @221 */ -/* srcp: ppxref.h:16 chain: @2673 */ -/* @2623 record_type name: @2648 unql: @2649 size: @593 */ -/* algn: 32 tag : struct flds: @2650 */ - - -/* @2642 identifier_node strg: ppstream lngt: 8 */ -/* @2615 type_decl name: @2642 type: @2643 scpe: @221 */ -/* srcp: ppapi.h:54 chain: @2644 */ -/* @2643 record_type name: @2615 unql: @2614 size: @634 */ -/* algn: 32 tag : struct flds: @2641 */ - - -/* @2765 identifier_node strg: ppkids lngt: 6 */ -/* @2743 type_decl name: @2765 type: @2766 scpe: @221 */ -/* srcp: ppload.h:16 chain: @2767 */ -/* @2766 record_type name: @2743 unql: @2742 size: @19 */ -/* algn: 32 tag : struct flds: @2764 */ - - -/* @2625 identifier_node strg: ppdoc lngt: 5 */ -/* @2605 record_type name: @2625 size: @2626 algn: 32 */ -/* tag : struct flds: @2627 */ - -/* @2526 identifier_node strg: ppref lngt: 5 */ -/* @2513 record_type name: @2526 size: @662 algn: 64 */ -/* tag : struct flds: @2527 */ - - -/* @2595 identifier_node strg: ppdict lngt: 6 */ -/* @2576 type_decl name: @2595 type: @2596 scpe: @221 */ -/* srcp: ppapi.h:45 chain: @2597 */ -/* @2596 record_type name: @2576 unql: @2575 size: @593 */ -/* algn: 32 tag : struct flds: @2594 */ - - -/* @2769 identifier_node strg: ppcrypt_status lngt: 14 */ -/* @2752 type_decl name: @2769 type: @2770 scpe: @221 */ -/* srcp: ppapi.h:295 chain: @2771 */ -/* @2770 enumeral_type name: @2752 unql: @2655 size: @5 */ -/* algn: 32 prec: 32 sign: signed */ -/* min : @6 max : @7 csts: @2681 */ - - -/* @2558 identifier_node strg: pparray lngt: 7 */ -/* @2541 type_decl name: @2558 type: @2559 scpe: @221 */ -/* srcp: ppapi.h:39 chain: @2560 */ -/* @2559 record_type name: @2541 unql: @2540 size: @19 */ -/* algn: 32 tag : struct flds: @2557 */ - - -/* @2817 identifier_node strg: aligned_data */ -/* @2801 type_decl name: @2817 type: @2818 scpe: @221 */ -/* srcp: ppheap.c:22 chain: @2819 */ -/* @2818 real_type name: @2801 unql: @99 size: @19 */ -/* algn: 64 prec: 64 */ - - -typedef long double aligned_data; - - -#define ALIGN_BUFF_BUCKET_SIZE 0x3000 /* heuristic value, found by running few tests */ -#ifdef __SIZEOF_POINTER__ -#define SIZE_OF_POINTER __SIZEOF_POINTER__ -#else -#define SIZE_OF_POINTER (sizeof(void *)) -#endif - -typedef struct _simplereg { - size_t bucket_pos; - size_t bucket_size; - size_t heap_instance; - aligned_data **align_data_set ; -} simplereg; - -/* By default static vars are initialized to NULL, but to be clear.. */ -static simplereg *align_set = NULL ; - -static void align_init_set(void){ - size_t size ; - - if (align_set) { - align_set->heap_instance++; - return ; - } - - align_set = malloc(sizeof(simplereg)); - if (!align_set) { - fprintf(stderr,"! fatal error: unable to setup master register for aligned pointers\n"); - exit(EXIT_FAILURE); - } - - size = SIZE_OF_POINTER*ALIGN_BUFF_BUCKET_SIZE; - align_set->align_data_set = malloc(size); - if (!align_set->align_data_set) { - fprintf(stderr,"! fatal error: unable to setup register for aligned pointers\n"); - exit(EXIT_FAILURE); - } - - align_set->bucket_pos = 0; - align_set->bucket_size = ALIGN_BUFF_BUCKET_SIZE; - align_set->heap_instance = 1; - memset(align_set->align_data_set, 0UL,size); -} - -static void align_save_into_set(aligned_data *p){ - if (align_set->bucket_pos >= align_set->bucket_size) { - size_t new_size; - aligned_data **align_data_set_new; - - if(!align_set->align_data_set){ - fprintf(stderr,"! fatal error: unable to save aligned pointer,corrupted set\n"); - exit(EXIT_FAILURE); - } - new_size = (ALIGN_BUFF_BUCKET_SIZE+align_set->bucket_size)*SIZE_OF_POINTER; - align_data_set_new = malloc(new_size); - if (!align_data_set_new) { - fprintf(stderr,"! fatal error: unable to save aligned pointer\n"); - exit(EXIT_FAILURE); - } - memset(align_data_set_new,0,new_size); - memcpy(align_data_set_new, align_set->align_data_set, align_set->bucket_size*SIZE_OF_POINTER); - free(align_set->align_data_set); - align_set->align_data_set = align_data_set_new ; - align_set->bucket_size += ALIGN_BUFF_BUCKET_SIZE; - } - if (align_set->bucket_pos>align_set->bucket_size){ - fprintf(stderr,"! fatal error: unable to save aligned pointer, wrong position\n"); - exit(EXIT_FAILURE); - } - align_set->align_data_set[align_set->bucket_pos] = p ; - align_set->bucket_pos++; - -} - -static void align_free_set(void){ - /* We don't know what heap does with its data, so free here is not secure */ - - if(align_set){ - if (align_set->heap_instance>1) { - align_set->heap_instance--; - } else if (align_set->heap_instance ==1) { - if (align_set->align_data_set){ - size_t p; - for(p=1;p<align_set->bucket_pos;p++){ - if (align_set->align_data_set[p]) { - free(align_set->align_data_set[p]); - align_set->align_data_set[p] = NULL; - } - } - free(align_set->align_data_set); - align_set->align_data_set = NULL; - } - align_set->heap_instance=0; - free(align_set); - align_set = NULL ; - } - } -} - -#endif /* PPHEAP_NEED_ALIGNMENT */ - - -static ppheap * ppheap_create (size_t size) -{ - ppheap *heap; - heap = (ppheap *)pp_malloc(sizeof(ppheap) + size * sizeof(uint8_t)); - heap->size = size; - heap->space = size; - heap->data = ppheap_head(heap); - heap->prev = NULL; - return heap; -} - -ppheap * ppheap_new (void) -{ -#ifdef PPHEAP_NEED_ALIGNMENT - align_init_set(); -#endif - return ppheap_create(PPHEAP_BUFFER); -} - -void ppheap_free (ppheap *heap) -{ - ppheap *prev; - do - { - prev = heap->prev; - pp_free(heap); - heap = prev; - } while (heap != NULL); -#ifdef PPHEAP_NEED_ALIGNMENT - align_free_set(); -#endif - -} - -void ppheap_renew (ppheap *heap) -{ // free all but first - ppheap *prev; - if ((prev = heap->prev) != NULL) - { - heap->prev = NULL; - ppheap_free(prev); - } - heap->size = heap->space; - heap->data = ppheap_head(heap); -} - -static ppheap * ppheap_insert_top (ppheap **pheap, size_t size) -{ - ppheap *heap; - heap = ppheap_create(size); - heap->prev = (*pheap); - *pheap = heap; - return heap; -} - -static ppheap * ppheap_insert_sub (ppheap **pheap, size_t size) -{ - ppheap *heap; - heap = ppheap_create(size); - heap->prev = (*pheap)->prev; - (*pheap)->prev = heap; - return heap; -} - -void * ppheap_take (ppheap **pheap, size_t size) -{ - ppheap *heap; - uint8_t *data; -#ifdef PPHEAP_NEED_ALIGNMENT - aligned_data *p_aligned_data; -#endif - heap = *pheap; - if (size <= heap->size) - ; - else if (heap->size <= PPHEAP_WASTE && size <= (PPHEAP_BUFFER >> 1)) - heap = ppheap_insert_top(pheap, PPHEAP_BUFFER); - else - heap = ppheap_insert_sub(pheap, size); - data = heap->data; - heap->data += size; - heap->size -= size; -#ifdef PPHEAP_NEED_ALIGNMENT - /* Todo: only if data%sizeof(aligned_data) != 0 */ - p_aligned_data = malloc(size); - if (!p_aligned_data) { - fprintf(stderr,"! fatal error: unable to setup aligned pointer for ppheap_take\n"); - exit(EXIT_FAILURE); - } - memcpy(p_aligned_data,data,size); - align_save_into_set(p_aligned_data); - return (void *)p_aligned_data; -#else - return (void *)data; -#endif - -} - - -/* iof buffer tied to a heap */ - -static ppheap * ppheap_resize (ppheap **pheap, size_t size) -{ - ppheap *heap; - heap = ppheap_create(size); - heap->prev = (*pheap)->prev; - memcpy(heap->data, (*pheap)->data, (*pheap)->space); // (*pheap)->size is irrelevant - pp_free(*pheap); - *pheap = heap; - return heap; -} - -static size_t ppheap_buffer_handler (iof *O, iof_mode mode) -{ - ppheap **pheap, *heap; - size_t objectsize, buffersize, neededsize; - uint8_t *copyfrom; - switch (mode) - { - case IOFWRITE: - /* apparently more space needed then assumed initsize */ - pheap = (ppheap **)O->link; - heap = *pheap; - objectsize = (size_t)(O->buf - heap->data); - buffersize = (size_t)(O->pos - O->buf); - neededsize = objectsize + (buffersize << 1); - if (ppheap_head(heap) < heap->data) - { - if (heap->size <= PPHEAP_WASTE && neededsize <= (PPHEAP_BUFFER >> 1)) - { - heap = ppheap_insert_top(pheap, PPHEAP_BUFFER); - copyfrom = heap->prev->data; - } - else - { - heap = ppheap_insert_sub(pheap, neededsize); - copyfrom = (*pheap)->data; - O->link = (void *)(&(*pheap)->prev); - } - memcpy(heap->data, copyfrom, objectsize + buffersize); - } - else - { /* the buffer was (re)initialized from a new empty heap and occupies its entire space */ - // ASSERT(ppheap_head(heap) == heap->data); - heap = ppheap_resize(pheap, neededsize); - } - O->buf = heap->data + objectsize; - O->pos = O->buf + buffersize; - O->end = heap->data + heap->size; - return (size_t)(O->end - O->pos); - case IOFFLUSH: - return 0; - case IOFCLOSE: - // O->buf = O->pos = O->end = NULL; - // O->link = NULL; - return 0; - default: - break; - } - return 0; -} - -iof * ppheap_buffer (ppheap **pheap, size_t objectsize, size_t initsize) -{ - static iof ppheap_buffer_iof = IOF_WRITER_STRUCT(ppheap_buffer_handler, NULL, NULL, 0, 0); - ppheap *heap; - size_t size; - size = objectsize + initsize; - heap = *pheap; - if (size <= heap->size) - ; - else if (heap->size <= PPHEAP_WASTE && size <= (PPHEAP_BUFFER >> 1)) - { - heap = ppheap_create(PPHEAP_BUFFER); - heap->prev = (*pheap); - *pheap = heap; - } - else - { - heap = ppheap_create(size); - heap->prev = (*pheap)->prev; - (*pheap)->prev = heap; - pheap = &(*pheap)->prev; // passed to ppheap_buffer_iof.link - } - ppheap_buffer_iof.buf = ppheap_buffer_iof.pos = heap->data + objectsize; - ppheap_buffer_iof.end = heap->data + heap->size; - ppheap_buffer_iof.link = pheap; // ASSERT(*pheap == heap) - return &ppheap_buffer_iof; -} - -/* -void * ppheap_buffer_data (iof *O, size_t *psize) -{ - ppheap *heap; - heap = *((ppheap **)(O->link)); - *psize = ppheap_buffer_size(O, heap); - return heap->data; -} -*/ - -void * ppheap_flush (iof *O, size_t *psize) // not from explicit ppheap ** !!! -{ - ppheap *heap; - uint8_t *data; - size_t size; -#ifdef PPHEAP_NEED_ALIGNMENT - aligned_data *p_aligned_data; -#endif - heap = *((ppheap **)(O->link)); - *psize = ppheap_buffer_size(O, heap); - size = *psize; - data = heap->data; -/* heap->data += *psize; - heap->size -= *psize; -*/ - heap->data += size; - heap->size -= size; - // O->buf = O->pos = O->end = NULL; - // O->link = NULL; - // iof_close(O); -#ifdef PPHEAP_NEED_ALIGNMENT - /* Todo: only if data%sizeof(aligned_data) != 0 */ - p_aligned_data = malloc(size); - if (!p_aligned_data) { - fprintf(stderr,"! fatal error: unable to setup aligned pointer for ppheap_flush\n"); - exit(EXIT_FAILURE); - } - memcpy(p_aligned_data,data,size); - align_save_into_set(p_aligned_data); - return (void *)p_aligned_data; -#else - return data; - -#endif - - -} - - diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppheap.h b/Build/source/texk/web2c/luatexdir/luapplib/ppheap.h deleted file mode 100644 index 128f9c56d62..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppheap.h +++ /dev/null @@ -1,29 +0,0 @@ - -#ifndef PP_HEAP_H -#define PP_HEAP_H - -#include "utilmem.h" - -#define pp_malloc util_malloc -#define pp_callic util_calloc -#define pprealloc util_realloc -#define pp_free util_free - -typedef struct ppheap ppheap; -struct ppheap { - size_t size; - size_t space; - uint8_t *data; - ppheap *prev; -}; - -ppheap * ppheap_new (void); -void ppheap_free (ppheap *heap); -void ppheap_renew (ppheap *heap); -void * ppheap_take (ppheap **pheap, size_t size); -iof * ppheap_buffer (ppheap **pheap, size_t objectsize, size_t initsize); -#define ppheap_buffer_size(O, heap) (size_t)((O)->pos - (heap)->data) // == (size_t)(O->buf - heap->data) + (size_t)(O->pos - O->buf); -//void * ppheap_buffer_data (iof *O, size_t *psize); -void * ppheap_flush (iof *O, size_t *psize); - -#endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/pptest3.c b/Build/source/texk/web2c/luatexdir/luapplib/pptest3.c deleted file mode 100644 index 0b96b229ad0..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/pptest3.c +++ /dev/null @@ -1,98 +0,0 @@ - -#include <stdio.h> -//#include "ppapi.h" -#include "pplib.h" -#include "assert.h" - -static int usage (const char *argv0) -{ - printf("pplib " pplib_version ", " pplib_author "\n"); - printf("usage: %s file1.pdf file2.pdf ...\n", argv0); - return 0; -} - -static void print_result_filter (ppstream *stream, int decode) -{ - ppstream_filter info; - size_t i; - - ppstream_filter_info(stream, &info, decode); - printf("when %s: /Filter [", decode ? "uncompressed" : "compressed"); - for (i = 0; i < info.count; ++i) - printf(" /%s", ppstream_filter_name[info.filters[i]]); - printf(" ]"); - if (info.params != NULL) - { - printf(" /DecodeParms ["); - for (i = 0; i < info.count; ++i) - printf(" %s", info.params[i] != NULL ? "<<...>>" : "null"); - printf(" ]"); - } - printf("\n"); -} - -static void print_stream_info (ppref *ref, ppstream *stream) -{ - size_t length; - printf("object %lu %lu R\n", (unsigned long)ref->number, (unsigned long)ref->version); - if (stream->flags & PPSTREAM_FILTER) - printf("filtered "); - else - printf("plain "); - if (stream->flags & PPSTREAM_IMAGE) - printf("image "); - else - printf("stream "); - if (stream->flags & PPSTREAM_ENCRYPTED) - printf("encrypted "); - if (stream->flags & PPSTREAM_NOT_SUPPORTED) - printf("invalid "); - if (!ppdict_rget_uint(stream->dict, "Length", &length)) - length = 0; - assert(stream->length == length); - printf("length %lu (/Length %lu)\n", (unsigned long)stream->length, (unsigned long)length); - print_result_filter(stream, 0); - print_result_filter(stream, 1); - printf("\n"); -} - -int main (int argc, const char **argv) -{ - const char *filepath; - int a; - ppdoc *pdf; - ppxref *xref; - ppxsec *xsec; - size_t xi; - ppuint refnum; - ppref *ref; - - if (argc < 2) - return usage(argv[0]); - for (a = 1; a < argc; ++a) - { - filepath = argv[a]; - printf("loading %s... ", filepath); - pdf = ppdoc_load(filepath); - if (pdf == NULL) - { - printf("failed\n"); - continue; - } - printf("done.\n"); - for (xref = ppdoc_xref(pdf); xref != NULL; xref = ppxref_prev(xref)) - { - for (xi = 0, xsec = xref->sects; xi < xref->size; ++xi, ++xsec) - { - for (refnum = xsec->first, ref = xsec->refs; refnum <= xsec->last; ++refnum, ++ref) - { - if (ref->object.type != PPSTREAM) - continue; - print_stream_info(ref, ref->object.stream); - } - } - } - ppdoc_free(pdf); - } - return 0; -} diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/CMakeLists.txt b/Build/source/texk/web2c/luatexdir/luapplib/src/CMakeLists.txt new file mode 100644 index 00000000000..36cc42135c2 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/CMakeLists.txt @@ -0,0 +1,151 @@ +cmake_minimum_required(VERSION 3.5) + +project(pplib + LANGUAGES C) +set(VERSION 1.0.5) + +set(CMAKE_C_STANDARD 99) + +add_library(pplib_utils STATIC + util/utilplat.h + util/utilcryptdef.h + util/utildecl.h + # + util/utilcrypt.c + util/utilcrypt.h + util/utiliof.c + util/utiliof.h + util/utillog.c + util/utillog.h + util/utilmd5.c + util/utilmd5.h + util/utilmem.c + util/utilmem.h + # + util/utilmemheap.c + util/utilmemheap.h + util/utilmemheapiof.c + util/utilmemheapiof.h + util/utilmeminfo.c + util/utilmeminfo.h + # + util/utilnumber.c + util/utilnumber.h + util/utilsha.c + util/utilsha.h +) + +target_include_directories(pplib_utils PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/util> +) + +target_link_libraries(pplib_utils + PUBLIC + m + zlib +) + +add_library(pplib_filters STATIC + util/utilbasexx.c + util/utilbasexx.h + util/utilflate.c + util/utilflate.h + util/utilfpred.c + util/utilfpred.h + util/utillzw.c + util/utillzw.h +) + +target_include_directories(pplib_filters PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/util> +) + +target_link_libraries(pplib_filters + PUBLIC + m + zlib +) + +add_library(pplib + ppapi.h + ppconf.h + pplib.h + # + pparray.c + pparray.h + ppcrypt.c + ppcrypt.h + ppdict.c + ppdict.h + ppfilter.h + ppheap.c + ppheap.h + ppload.c + ppload.h + ppstream.c + ppstream.h + ppxref.c + ppxref.h +) + +target_include_directories(pplib PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/util> + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> +) + +target_link_libraries(pplib + PRIVATE + pplib_filters + pplib_utils +) + +target_include_directories(pplib + PRIVATE + util +) + +if (MSVC) + #set(warning_flags '') # /W4 /WX +else (MSVC) + set(warning_flags + -Wall + -Wextra + -Wcast-align + -Wcast-qual + -Wdeclaration-after-statement + -Wnested-externs + -Wno-unknown-pragmas + -Wpointer-arith + -Wwrite-strings + ) + + foreach(target pplib_utils pplib_filters pplib) + target_compile_options(${target} PRIVATE ${warning_flags}) + endforeach() +endif (MSVC) + +set_target_properties(pplib + PROPERTIES + PUBLIC_HEADER "ppapi.h;ppconf.h;pplib.h" +) + +add_library(pplib::pplib ALIAS pplib) + +install(TARGETS pplib + EXPORT pplib + DESTINATION lib +) + +enable_testing() + +list(APPEND tests pptest1 pptest2 pptest3) + +foreach(_test IN LISTS tests) + add_executable(${_test} ${_test}.c) + target_link_libraries(${_test} PRIVATE pplib) + + add_test( + NAME pplib.${_test} + COMMAND $<TARGET_FILE:${_test}> + ) +endforeach() diff --git a/Build/source/texk/web2c/luatexdir/luapplib/Makefile.orig b/Build/source/texk/web2c/luatexdir/luapplib/src/Makefile index 823c68f6bb9..de67505649a 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/Makefile.orig +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/Makefile @@ -1,89 +1,99 @@ -
-ifeq ($(ARCH),)
- ARCH=x64
-endif
-
-UNAME:=$(shell uname)
-ifeq ($(UNAME),Linux)
- BUILDSUFFIX=_ux_$(ARCH)
- SOEXT=.so
- EXEEXT=
- STATICCOPTS=
-# SHAREDCOPTS=-fPIC
- LFLAGS=
- LIBS=-lm
-else
- BUILDSUFFIX=_win_$(ARCH)
- SOEXT=.dll
- EXEEXT=.exe
- STATICCOPTS=
-# SHAREDCOPTS=-DPPDLL
- LFLAGS = -Wl,--output-def,$@.def,--out-implib,$@.a
- LIBS=
-endif
-
-CC=gcc
-W=-Wall -Wunused -Wimplicit -Wreturn-type -Wdeclaration-after-statement -Wno-unknown-pragmas -Wmissing-prototypes -Wmissing-declarations -Wparentheses -Wswitch -Wtrigraphs -Wcast-qual -Wcast-align -Wwrite-strings -Wold-style-definition -Wpointer-arith
-#W=-Wall
-CFLAGS=$(W) -O2
-
-OBJEXT=$(BUILDSUFFIX).o
-
-PPUTILS=utilmem utillog utilnumber utiliof utilmd5 utilsha utilcrypt
-PPFILTERS=utilbasexx utilflate utillzw utilfpred
-PPMODULES=ppheap pparray ppdict ppstream ppcrypt ppxref ppload
-
-OUTDIR=build
-UTILSDIR=util
-
-PPSTATICUTILSOBJ=$(patsubst %, $(OUTDIR)/%$(OBJEXT), $(PPUTILS))
-PPSTATICFILTERSOBJ=$(patsubst %, $(OUTDIR)/%$(OBJEXT), $(PPFILTERS))
-PPSTATICOBJ=$(patsubst %, $(OUTDIR)/%$(OBJEXT), $(PPMODULES))
-PPSTATICLIB=$(OUTDIR)/libpp.static$(BUILDSUFFIX).a
-
-# dependencies
-FLATEDIR=zlib
-FLATELIB=$(FLATEDIR)/libz.static$(BUILDSUFFIX).a
-PPSTATICDEPS=$(FLATELIB)
-
-# test programm
-PPTEST1=$(OUTDIR)/pptest1$(EXEEXT)
-PPTEST2=$(OUTDIR)/pptest2$(EXEEXT)
-PPTEST3=$(OUTDIR)/pptest3$(EXEEXT)
-
-# includes
-INC=-I $(UTILSDIR)
-AUX=-I $(FLATEDIR)
-
-default: md $(PPSTATICLIB) $(PPTEST1) $(PPTEST2) $(PPTEST3)
-
-md:
- @[ -d $(OUTDIR) ] || mkdir -p $(OUTDIR)
-
-$(PPSTATICOBJ): $(OUTDIR)/%$(OBJEXT): %.c %.h
- $(CC) $(CFLAGS) $(STATICCOPTS) $(INC) -o $@ -c $<
-
-$(PPSTATICUTILSOBJ): $(OUTDIR)/%$(OBJEXT): $(UTILSDIR)/%.c $(UTILSDIR)/%.h
- $(CC) $(CFLAGS) $(STATICCOPTS) $(INC) -o $@ -c $<
-
-$(PPSTATICFILTERSOBJ): $(OUTDIR)/%$(OBJEXT): $(UTILSDIR)/%.c $(UTILSDIR)/%.h
- $(CC) $(CFLAGS) $(STATICCOPTS) $(INC) $(AUX) -o $@ -c $<
-
-$(PPSTATICLIB): $(PPSTATICOBJ) $(PPSTATICUTILSOBJ) $(PPSTATICFILTERSOBJ)
- ar rcs $@ $^
- strip -N print_hex $@
-
-$(PPTEST1): $(PPSTATICLIB) pptest1.c
- $(CC) $(CFLAGS) $(STATICCOPTS) -o $(OUTDIR)/pptest1$(OBJEXT) -c pptest1.c
- $(CC) -static-libgcc $(CFLAGS) -o $(PPTEST1) $(OUTDIR)/pptest1$(OBJEXT) $(PPSTATICLIB) $(PPSTATICDEPS) $(LIBS)
-
-$(PPTEST2): $(PPSTATICLIB) pptest2.c
- $(CC) $(CFLAGS) $(STATICCOPTS) -o $(OUTDIR)/pptest2$(OBJEXT) -c pptest2.c
- $(CC) -static-libgcc $(CFLAGS) -o $(PPTEST2) $(OUTDIR)/pptest2$(OBJEXT) $(PPSTATICLIB) $(PPSTATICDEPS) $(LIBS)
-
-$(PPTEST3): $(PPSTATICLIB) pptest3.c
- $(CC) $(CFLAGS) $(STATICCOPTS) -I util -o $(OUTDIR)/pptest3$(OBJEXT) -c pptest3.c
- $(CC) -static-libgcc $(CFLAGS) -o $(PPTEST3) $(OUTDIR)/pptest3$(OBJEXT) $(PPSTATICLIB) $(PPSTATICDEPS) $(LIBS)
-
-clean:
- rm -f $(OUTDIR)/*$(OBJEXT) $(OUTDIR)/*.a $(OUTDIR)/*$(EXEEXT)
+ +ifeq ($(ARCH),) + ARCH=x64 +endif + +UNAME:=$(shell uname) +ifeq ($(UNAME),Linux) + BUILDSUFFIX=_ux_$(ARCH) + SOEXT=.so + EXEEXT= +# SHAREDCOPTS=-fPIC + LFLAGS= + LIBS=-lm +else + BUILDSUFFIX=_win_$(ARCH) + SOEXT=.dll + EXEEXT=.exe +# SHAREDCOPTS=-DPPDLL + LFLAGS = -Wl,--output-def,$@.def,--out-implib,$@.a + LIBS= +endif + +CC=gcc +WLUIGI=-Wall -Wextra -Wunused -Wimplicit -Wreturn-type -Wdeclaration-after-statement -Wno-unknown-pragmas -Wmissing-prototypes -Wmissing-declarations -Wparentheses -Wswitch -Wtrigraphs -Wcast-qual -Wcast-align -Wwrite-strings -Wold-style-definition -Wpointer-arith +WHANS=-Wall -Wextra -Wcast-align -Wcast-qual -Wnested-externs -Wwrite-strings -Wdeclaration-after-statement -Wno-unknown-pragmas -Wpointer-arith +W=$(WLUIGI) + +CFLAGS=$(W) -O3 + +OBJEXT=$(BUILDSUFFIX).o + +PPALLOC=utilmem utilmemheap utilmemheapiof utilmeminfo +PPUTILS=utillog utilnumber utiliof utilmd5 utilsha utilcrypt +PPFILTERS=utilbasexx utilflate utillzw utilfpred +PPMODULES=ppheap pparray ppdict ppstream ppcrypt ppxref ppload + +OUTDIR=build +UTILSDIR=util + +PPSTATICALLOCOBJ=$(patsubst %, $(OUTDIR)/%$(OBJEXT), $(PPALLOC)) +PPSTATICUTILSOBJ=$(patsubst %, $(OUTDIR)/%$(OBJEXT), $(PPUTILS)) +PPSTATICFILTERSOBJ=$(patsubst %, $(OUTDIR)/%$(OBJEXT), $(PPFILTERS)) +PPSTATICOBJ=$(patsubst %, $(OUTDIR)/%$(OBJEXT), $(PPMODULES)) +PPSTATICLIB=$(OUTDIR)/libpp.static$(BUILDSUFFIX).a + +# dependencies +FLATEDIR=../zlib +FLATELIB=$(FLATEDIR)/libz.static$(BUILDSUFFIX).a +PPSTATICDEPS=$(FLATELIB) + +# tests +TESTDIR=../../pplib-tests +PPTEST1=$(OUTDIR)/pptest1$(EXEEXT) +PPTEST2=$(OUTDIR)/pptest2$(EXEEXT) +PPTEST3=$(OUTDIR)/pptest3$(EXEEXT) + +# includes +INC=-I $(UTILSDIR) +AUX=-I $(FLATEDIR) + +default: md $(PPSTATICLIB) $(PPTEST1) $(PPTEST2) $(PPTEST3) $(PPTEST4) + +md: + @[ -d $(OUTDIR) ] || mkdir -p $(OUTDIR) + +$(PPSTATICOBJ): $(OUTDIR)/%$(OBJEXT): %.c %.h + $(CC) $(CFLAGS) $(INC) -o $@ -c $< + +$(PPSTATICALLOCOBJ): $(OUTDIR)/%$(OBJEXT): $(UTILSDIR)/%.c $(UTILSDIR)/%.h + $(CC) $(CFLAGS) $(INC) -o $@ -c $< + +$(PPSTATICUTILSOBJ): $(OUTDIR)/%$(OBJEXT): $(UTILSDIR)/%.c $(UTILSDIR)/%.h + $(CC) $(CFLAGS) $(INC) -o $@ -c $< + +$(PPSTATICFILTERSOBJ): $(OUTDIR)/%$(OBJEXT): $(UTILSDIR)/%.c $(UTILSDIR)/%.h + $(CC) $(CFLAGS) $(INC) $(AUX) -o $@ -c $< + +$(PPSTATICLIB): $(PPSTATICOBJ) $(PPSTATICALLOCOBJ) $(PPSTATICUTILSOBJ) $(PPSTATICFILTERSOBJ) + ar rcs $@ $^ + +$(PPTEST1): $(PPSTATICLIB) pptest1.c + $(CC) $(CFLAGS) -o $(OUTDIR)/pptest1$(OBJEXT) -c pptest1.c + $(CC) -static-libgcc $(CFLAGS) -o $(PPTEST1) $(OUTDIR)/pptest1$(OBJEXT) $(PPSTATICLIB) $(PPSTATICDEPS) $(LIBS) + +$(PPTEST2): $(PPSTATICLIB) pptest2.c + $(CC) $(CFLAGS) -o $(OUTDIR)/pptest2$(OBJEXT) -c pptest2.c + $(CC) -static-libgcc $(CFLAGS) -o $(PPTEST2) $(OUTDIR)/pptest2$(OBJEXT) $(PPSTATICLIB) $(PPSTATICDEPS) $(LIBS) + +$(PPTEST3): $(PPSTATICLIB) pptest3.c + $(CC) $(CFLAGS) -I util -o $(OUTDIR)/pptest3$(OBJEXT) -c pptest3.c + $(CC) -static-libgcc $(CFLAGS) -o $(PPTEST3) $(OUTDIR)/pptest3$(OBJEXT) $(PPSTATICLIB) $(PPSTATICDEPS) $(LIBS) + +clean: + rm -f $(OUTDIR)/*$(OBJEXT) $(OUTDIR)/*.a $(OUTDIR)/*$(EXEEXT) + +test: $(PPTEST1) $(PPTEST2) $(PPTEST3) + build/pptest1 $(TESTDIR)/*.pdf $(TESTDIR)/crypt/*.pdf >pptest1.log + build/pptest2 $(TESTDIR)/*.pdf $(TESTDIR)/crypt/*.pdf >pptest2.log + build/pptest3 $(TESTDIR)/*.pdf $(TESTDIR)/crypt/*.pdf >pptest3.log diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/Makefile.vc b/Build/source/texk/web2c/luatexdir/luapplib/src/Makefile.vc new file mode 100644 index 00000000000..481d9b20ab7 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/Makefile.vc @@ -0,0 +1,98 @@ + +CC=cl /nologo +LN=link /nologo +AR=lib /nologo # LIB variable has a special meaning for msvc + +CFLAGS=/W3 /D_CRT_SECURE_NO_DEPRECATE /O2 + +# hans +# 5045: spectre +# 4820: local vars with same name as outer variable +# 4456: local vars with same name as outer variable +# 4457: local vars with same function parameter +# 4668: missing defines +# 4244: assignment in conditional expression +# 4127: constant conditional expression +# 4131: old style declarator +# 4464: relative include path +# 4201: nonstandard extension used: nameless struct/union +# 4710: no inlined +# 4711: inline expansion +# 4706: assignment in conditionals + +#WFLAGS= /W3 /D_CRT_SECURE_NO_DEPRECATE +WFLAGS= /Wall /D_CRT_SECURE_NO_DEPRECATE /wd5045 /wd4820 /wd4456 /wd4457 /wd4668 /wd4244 /wd4127 /wd4131 /wd4464 /wd4201 /wd4710 /wd4711 +CFLAGS= $(WFLAGS) /O2 + +#LFLAGS = /NODEFAULTLIB:LIBCMT # produces binary dependent from redistributable +LFLAGS = /NOIMPLIB + +PPALLOC=utilmem.c utilmemheap.c utilmemheapiof.c utilmeminfo.c +PPUTILS=utillog.c utilnumber.c utiliof.c utilmd5.c utilsha.c utilcrypt.c +PPFILTERS=utilbasexx.c utilflate.c utillzw.c utilfpred.c +PPMODULES=ppheap.c pparray.c ppdict.c ppstream.c ppcrypt.c ppxref.c ppload.c + +OUTDIR=build +UTILSDIR=util + +PPSTATICALLOCOBJ=$(PPALLOC:.c=.obj) +PPSTATICALLOCOBJ=$(PPSTATICALLOCOBJ:util=build\util) +PPSTATICUTILSOBJ=$(PPUTILS:.c=.obj) +PPSTATICUTILSOBJ=$(PPSTATICUTILSOBJ:util=build\util) +PPSTATICFILTERSOBJ=$(PPFILTERS:.c=.obj) +PPSTATICFILTERSOBJ=$(PPSTATICFILTERSOBJ:util=build\util) +PPSTATICOBJ=$(PPMODULES:.c=.obj) +PPSTATICOBJ=$(PPSTATICOBJ:pp=build\pp) +PPSTATICLIB=build\pp.lib + +# dependencies +FLATEDIR=..\zlib +FLATELIB=$(FLATEDIR)\zlib.static.lib +PPSTATICDEPS=$(FLATELIB) + +# tests +TESTDIR=..\..\pplib-tests +PPTEST1=build\pptest1.exe +PPTEST2=build\pptest2.exe +PPTEST3=build\pptest3.exe + +# includes +INC=/I $(UTILSDIR) +AUX=/I $(FLATEDIR) + +default: $(PPSTATICLIB) $(PPTEST1) $(PPTEST2) $(PPTEST3) $(PPTEST4) + +$(PPSTATICOBJ): $(*B).c + $(CC) $(CFLAGS) $(INC) /Fo:$@ /c $** + +$(PPSTATICALLOCOBJ): $(UTILSDIR)\$(*B).c + $(CC) $(CFLAGS) $(INC) /Fo:$@ /c $** + +$(PPSTATICUTILSOBJ): $(UTILSDIR)\$(*B).c + $(CC) $(CFLAGS) $(INC) /Fo:$@ /c $** + +$(PPSTATICFILTERSOBJ): $(UTILSDIR)\$(*B).c + $(CC) $(CFLAGS) $(INC) $(AUX) /Fo:$@ /c $** + +$(PPSTATICLIB): $(PPSTATICOBJ) $(PPSTATICALLOCOBJ) $(PPSTATICUTILSOBJ) $(PPSTATICFILTERSOBJ) + $(AR) /OUT:$@ $** + +$(PPTEST1): $(PPSTATICLIB) pptest1.c + $(CC) $(CFLAGS) /Fo:build\pptest1.obj /c pptest1.c + $(LN) $(LFLAGS) /OUT:$(PPTEST1) build\pptest1.obj $(PPSTATICLIB) $(PPSTATICDEPS) $(LIBS) + +$(PPTEST2): $(PPSTATICLIB) pptest2.c + $(CC) $(CFLAGS) /Fo:build\pptest2.obj /c pptest2.c + $(LN) $(LFLAGS) /OUT:$(PPTEST2) build\pptest2.obj $(PPSTATICLIB) $(PPSTATICDEPS) $(LIBS) + +$(PPTEST3): $(PPSTATICLIB) pptest3.c + $(CC) $(CFLAGS) /I util /Fo:build\pptest3.obj /c pptest3.c + $(LN) $(LFLAGS) /OUT:$(PPTEST3) build\pptest3.obj $(PPSTATICLIB) $(PPSTATICDEPS) $(LIBS) + +clean: + del /q build\*.obj build\*.lib build\*.exe + +test: $(PPTEST1) $(PPTEST2) $(PPTEST3) + build\pptest1 $(TESTDIR)\*.pdf $(TESTDIR)/crypt\*.pdf >pptest1.log + build\pptest2 $(TESTDIR)\*.pdf $(TESTDIR)/crypt\*.pdf >pptest2.log + build\pptest3 $(TESTDIR)\*.pdf $(TESTDIR)/crypt\*.pdf >pptest3.log diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppapi.h b/Build/source/texk/web2c/luatexdir/luapplib/src/ppapi.h index a61ca04a089..94956f8cb56 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppapi.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppapi.h @@ -8,7 +8,7 @@ #include "ppconf.h" -#define pplib_version "v1.03" +#define pplib_version "v2.05 less toxic i hope" #define pplib_author "p.jackowski@gust.org.pl" /* types */ @@ -16,54 +16,41 @@ typedef int64_t ppint; typedef size_t ppuint; // machine word +typedef char ppbyte; + typedef double ppnum; -typedef char * ppname; -typedef char * ppstring; -typedef struct { +typedef struct ppname ppname; +typedef struct ppstring ppstring; + +struct ppname { + ppbyte *data; size_t size; + ppname *alterego; int flags; -} _ppname; +}; -typedef struct { +struct ppstring { + ppbyte *data; size_t size; + ppstring *alterego; int flags; -} _ppstring; +}; typedef struct ppobj ppobj; typedef struct ppref ppref; - -#if ARM_COMPLIANT typedef struct { ppobj *data; size_t size; - ppnum PPARRAY_ALIGNMENT; } pparray; -#else -typedef struct { - ppobj *data; - size_t size; -} pparray; -#endif - -#if ARM_COMPLIANT typedef struct { ppobj *data; - ppname *keys; + ppname **keys; size_t size; - ppnum PPDICT_ALIGNMENT; } ppdict; -#else -typedef struct { - ppobj *data; - ppname *keys; - size_t size; -} ppdict; -#endif - typedef enum { PPSTREAM_BASE16 = 0, PPSTREAM_BASE85, @@ -90,12 +77,12 @@ typedef struct { size_t length; ppstream_filter filter; ppobj *filespec; - ppstring cryptkey; + ppstring *cryptkey; int flags; } ppstream; PPDEF extern const char * ppstream_filter_name[]; -PPAPI int ppstream_filter_type (ppname filtername, ppstreamtp *filtertype); +PPAPI int ppstream_filter_type (ppname *filtername, ppstreamtp *filtertype); PPAPI void ppstream_filter_info (ppstream *stream, ppstream_filter *info, int decode); #define PPSTREAM_FILTER (1<<0) @@ -128,18 +115,18 @@ typedef enum { PPDEF extern const char * ppobj_kind[]; struct ppobj { - ppobjtp type; union { ppint integer; ppnum number; - ppname name; - ppstring string; + ppname *name; + ppstring *string; pparray *array; ppdict *dict; ppstream *stream; ppref *ref; void *any; }; + ppobjtp type; }; typedef struct ppxref ppxref; @@ -187,34 +174,27 @@ typedef struct ppdoc ppdoc; /* name */ -#define ppname_is(name, s) (memcmp(name, s, sizeof("" s) - 1) == 0) -#define ppname_eq(name, n) (memcmp(name, s, ppname_size(name)) == 0) +#define ppname_is(name, s) (memcmp((name)->data, s, sizeof("" s) - 1) == 0) +#define ppname_eq(name, n) (memcmp((name)->data, s, (name)->size) == 0) -#if ARM_COMPLIANT -#define _ppname_ghost(name) (((const _ppname *)((void *)name)) - 1) -#else -#define _ppname_ghost(name) (((const _ppname *)(name)) - 1) -#endif - -#define ppname_size(name) (_ppname_ghost(name)->size) -#define ppname_exec(name) (_ppname_ghost(name)->flags & PPNAME_EXEC) +#define ppname_size(name) ((name)->size) +#define ppname_exec(name) ((name)->flags & PPNAME_EXEC) +#define ppname_data(name) ((name)->data) #define PPNAME_ENCODED (1 << 0) #define PPNAME_DECODED (1 << 1) #define PPNAME_EXEC (1 << 1) -PPAPI ppname ppname_decoded (ppname name); -PPAPI ppname ppname_encoded (ppname name); +PPAPI ppname * ppname_decoded (ppname *name); +PPAPI ppname * ppname_encoded (ppname *name); -/* string */ +PPAPI ppbyte * ppname_decoded_data (ppname *name); +PPAPI ppbyte * ppname_encoded_data (ppname *name); -#if ARM_COMPLIANT -#define _ppstring_ghost(string) (((const _ppstring *)((void *)string)) - 1) -#else -#define _ppstring_ghost(string) (((const _ppstring *)(string)) - 1) -#endif +/* string */ -#define ppstring_size(string) (_ppstring_ghost(string)->size) +#define ppstring_size(string) ((string)->size) +#define ppstring_data(string) ((string)->data) #define PPSTRING_ENCODED (1 << 0) #define PPSTRING_DECODED (1 << 1) @@ -225,12 +205,15 @@ PPAPI ppname ppname_encoded (ppname name); #define PPSTRING_UTF16BE (1 << 5) #define PPSTRING_UTF16LE (1 << 6) -#define ppstring_type(string) (_ppstring_ghost(string)->flags & (PPSTRING_BASE16|PPSTRING_BASE85)) -#define ppstring_hex(string) (_ppstring_ghost(string)->flags & PPSTRING_BASE16) -#define ppstring_utf(string) (_ppstring_ghost(string)->flags & (PPSTRING_UTF16BE|PPSTRING_UTF16LE)) +#define ppstring_type(string) ((string)->flags & (PPSTRING_BASE16|PPSTRING_BASE85)) +#define ppstring_hex(string) ((string)->flags & PPSTRING_BASE16) +#define ppstring_utf(string) ((string)->flags & (PPSTRING_UTF16BE|PPSTRING_UTF16LE)) + +PPAPI ppstring * ppstring_decoded (ppstring *string); +PPAPI ppstring * ppstring_encoded (ppstring *string); -PPAPI ppstring ppstring_decoded (ppstring string); -PPAPI ppstring ppstring_encoded (ppstring string); +PPAPI ppbyte * ppstring_decoded_data (ppstring *string); +PPAPI ppbyte * ppstring_encoded_data (ppstring *string); /* array */ @@ -247,8 +230,8 @@ PPAPI int pparray_get_bool (pparray *array, size_t index, int *v); PPAPI int pparray_get_int (pparray *array, size_t index, ppint *v); PPAPI int pparray_get_uint (pparray *array, size_t index, ppuint *v); PPAPI int pparray_get_num (pparray *array, size_t index, ppnum *v); -PPAPI ppname pparray_get_name (pparray *array, size_t index); -PPAPI ppstring pparray_get_string (pparray *array, size_t index); +PPAPI ppname * pparray_get_name (pparray *array, size_t index); +PPAPI ppstring * pparray_get_string (pparray *array, size_t index); PPAPI pparray * pparray_get_array (pparray *array, size_t index); PPAPI ppdict * pparray_get_dict (pparray *array, size_t index); //PPAPI ppstream * pparray_get_stream (pparray *array, size_t index); @@ -259,8 +242,8 @@ PPAPI int pparray_rget_bool (pparray *array, size_t index, int *v); PPAPI int pparray_rget_int (pparray *array, size_t index, ppint *v); PPAPI int pparray_rget_uint (pparray *array, size_t index, ppuint *v); PPAPI int pparray_rget_num (pparray *array, size_t index, ppnum *v); -PPAPI ppname pparray_rget_name (pparray *array, size_t index); -PPAPI ppstring pparray_rget_string (pparray *array, size_t index); +PPAPI ppname * pparray_rget_name (pparray *array, size_t index); +PPAPI ppstring * pparray_rget_string (pparray *array, size_t index); PPAPI pparray * pparray_rget_array (pparray *array, size_t index); PPAPI ppdict * pparray_rget_dict (pparray *array, size_t index); PPAPI ppstream * pparray_rget_stream (pparray *array, size_t index); @@ -277,8 +260,8 @@ PPAPI int ppdict_get_bool (ppdict *dict, const char *name, int *v); PPAPI int ppdict_get_int (ppdict *dict, const char *name, ppint *v); PPAPI int ppdict_get_uint (ppdict *dict, const char *name, ppuint *v); PPAPI int ppdict_get_num (ppdict *dict, const char *name, ppnum *v); -PPAPI ppname ppdict_get_name (ppdict *dict, const char *name); -PPAPI ppstring ppdict_get_string (ppdict *dict, const char *name); +PPAPI ppname * ppdict_get_name (ppdict *dict, const char *name); +PPAPI ppstring * ppdict_get_string (ppdict *dict, const char *name); PPAPI pparray * ppdict_get_array (ppdict *dict, const char *name); PPAPI ppdict * ppdict_get_dict (ppdict *dict, const char *name); //PPAPI ppstream * ppdict_get_stream (ppdict *dict, const char *name); @@ -289,8 +272,8 @@ PPAPI int ppdict_rget_bool (ppdict *dict, const char *name, int *v); PPAPI int ppdict_rget_int (ppdict *dict, const char *name, ppint *v); PPAPI int ppdict_rget_uint (ppdict *dict, const char *name, ppuint *v); PPAPI int ppdict_rget_num (ppdict *dict, const char *name, ppnum *v); -PPAPI ppname ppdict_rget_name (ppdict *dict, const char *name); -PPAPI ppstring ppdict_rget_string (ppdict *dict, const char *name); +PPAPI ppname * ppdict_rget_name (ppdict *dict, const char *name); +PPAPI ppstring * ppdict_rget_string (ppdict *dict, const char *name); PPAPI pparray * ppdict_rget_array (ppdict *dict, const char *name); PPAPI ppdict * ppdict_rget_dict (ppdict *dict, const char *name); PPAPI ppstream * ppdict_rget_stream (ppdict *dict, const char *name); @@ -328,6 +311,8 @@ PPAPI ppref * ppxref_find (ppxref *xref, ppuint refnumber); /* doc */ PPAPI ppdoc * ppdoc_load (const char *filename); +PPAPI ppdoc * ppdoc_filehandle (FILE *file, int closefile); +#define ppdoc_file(file) ppdoc_filehandle(file, 1) PPAPI ppdoc * ppdoc_mem (const void *data, size_t size); PPAPI void ppdoc_free (ppdoc *pdf); @@ -378,8 +363,8 @@ PPAPI void ppcontext_free (ppcontext *context); /* contents parser */ -PPAPI ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname); -PPAPI ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname); +PPAPI ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname **pname); +PPAPI ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname **pname); PPAPI ppobj * ppcontents_parse (ppcontext *context, ppstream *stream, size_t *psize); /* boxes and transforms */ diff --git a/Build/source/texk/web2c/luatexdir/luapplib/pparray.c b/Build/source/texk/web2c/luatexdir/luapplib/src/pparray.c index 25e8c495038..944596bdc1f 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/pparray.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/pparray.c @@ -1,14 +1,13 @@ #include "pplib.h" -pparray * pparray_create (const ppobj *stackpos, size_t size, ppheap **pheap) -{ - pparray *array; - ppobj *data; - array = (pparray *)ppheap_take(pheap, sizeof(pparray) + size * sizeof(ppobj)); - array->size = size; - array->data = data = (ppobj *)(array + 1); - memcpy(data, stackpos, size * sizeof(ppobj)); +pparray * pparray_create (const ppobj *stackpos, size_t size, ppheap *heap) +{ + pparray *array; + array = (pparray *)ppstruct_take(heap, sizeof(pparray)); + array->data = (ppobj *)ppstruct_take(heap, size * sizeof(ppobj)); // separate chunk, alignment requirements warning otherwise + array->size = size; + memcpy(array->data, stackpos, size * sizeof(ppobj)); return array; } @@ -71,25 +70,25 @@ int pparray_rget_num (pparray *array, size_t index, ppnum *v) return (obj = pparray_get(array, index)) != NULL ? ppobj_rget_num(obj, *v) : 0; } -ppname pparray_get_name (pparray *array, size_t index) +ppname * pparray_get_name (pparray *array, size_t index) { ppobj *obj; return (obj = pparray_get(array, index)) != NULL ? ppobj_get_name(obj) : NULL; } -ppname pparray_rget_name (pparray *array, size_t index) +ppname * pparray_rget_name (pparray *array, size_t index) { ppobj *obj; return (obj = pparray_get(array, index)) != NULL ? ppobj_rget_name(obj) : NULL; } -ppstring pparray_get_string (pparray *array, size_t index) +ppstring * pparray_get_string (pparray *array, size_t index) { ppobj *obj; return (obj = pparray_get(array, index)) != NULL ? ppobj_get_string(obj) : NULL; } -ppstring pparray_rget_string (pparray *array, size_t index) +ppstring * pparray_rget_string (pparray *array, size_t index) { ppobj *obj; return (obj = pparray_get(array, index)) != NULL ? ppobj_rget_string(obj) : NULL; diff --git a/Build/source/texk/web2c/luatexdir/luapplib/pparray.h b/Build/source/texk/web2c/luatexdir/luapplib/src/pparray.h index 6fdd8b8143f..df0d8e8b2c2 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/pparray.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/pparray.h @@ -2,6 +2,6 @@ #ifndef PP_ARRAY_H #define PP_ARRAY_H -pparray * pparray_create (const ppobj *stack, size_t size, ppheap **pheap); +pparray * pparray_create (const ppobj *stack, size_t size, ppheap *heap); #endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppconf.h b/Build/source/texk/web2c/luatexdir/luapplib/src/ppconf.h index be0683c8551..0211eb51e90 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppconf.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppconf.h @@ -2,16 +2,6 @@ #ifndef PP_CONF_H #define PP_CONF_H -//#include "utilarm.h" // keep in sync -#if defined __arm__ || defined __ARM__ || defined ARM || defined __ARM || defined __arm || defined __ARM_ARCH ||defined __aarch64__ ||defined( __sparc) -# define ARM_COMPLIANT 1 -#else -# define ARM_COMPLIANT 0 -#endif - -/* we impose this */ -/*#define ARM_COMPLIANT 1*/ - /* Aux flags: PPDLL -- indicates a part of a shared library diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppcrypt.c b/Build/source/texk/web2c/luatexdir/luapplib/src/ppcrypt.c index faab9af51c3..266bacc29b2 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppcrypt.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppcrypt.c @@ -6,21 +6,21 @@ /* crypt struct */ -static ppcrypt * ppcrypt_create (ppheap **pheap) +static ppcrypt * ppcrypt_create (ppheap *heap) { ppcrypt *crypt; - crypt = (ppcrypt *)ppheap_take(pheap, sizeof(ppcrypt)); + crypt = (ppcrypt *)ppstruct_take(heap, sizeof(ppcrypt)); memset(crypt, 0, sizeof(ppcrypt)); return crypt; } -int ppcrypt_type (ppcrypt *crypt, ppname cryptname, ppuint *length, int *cryptflags) +int ppcrypt_type (ppcrypt *crypt, ppname *cryptname, ppuint *length, int *cryptflags) { ppdict *filterdict; - ppname filtertype; + ppname *filtertype; int cryptmd = 0, default256 = 0; - if (crypt->map == NULL || (filterdict = ppdict_rget_dict(crypt->map, cryptname)) == NULL) + if (crypt->map == NULL || (filterdict = ppdict_rget_dict(crypt->map, cryptname->data)) == NULL) return 0; if ((filtertype = ppdict_get_name(filterdict, "CFM")) == NULL) return 0; @@ -72,15 +72,16 @@ static void ppcrypt_retrieve_userpass (ppcrypt *crypt, const void *ownerkey, siz uint8_t temp[16], rc4key[32], rc4key2[32]; uint8_t i; ppuint k; + md5_state md5; - md5init(); - md5add(crypt->ownerpass, 32); - md5put(rc4key); + md5_digest_init(&md5); + md5_digest_add(&md5, crypt->ownerpass, 32); + md5_digest_get(&md5, rc4key, MD5_BYTES); if (crypt->algorithm_revision >= 3) { for (i = 0; i < 50; ++i) { - pplib_md5(rc4key, 16, temp); + md5_digest(rc4key, 16, temp, MD5_BYTES); memcpy(rc4key, temp, 16); } } @@ -108,25 +109,26 @@ static void ppcrypt_filekey (ppcrypt *crypt, const void *ownerkey, size_t ownerk uint32_t p; uint8_t permissions[4], temp[16]; int i; + md5_state md5; - md5init(); - md5add(crypt->userpass, 32); - md5add(ownerkey, ownerkeysize); + md5_digest_init(&md5); + md5_digest_add(&md5, crypt->userpass, 32); + md5_digest_add(&md5, ownerkey, ownerkeysize); p = (uint32_t)crypt->permissions; - permissions[0] = get_byte1(p); - permissions[1] = get_byte2(p); - permissions[2] = get_byte3(p); - permissions[3] = get_byte4(p); - md5add(permissions, 4); - md5add(id, idsize); + permissions[0] = get_number_byte1(p); + permissions[1] = get_number_byte2(p); + permissions[2] = get_number_byte3(p); + permissions[3] = get_number_byte4(p); + md5_digest_add(&md5, permissions, 4); + md5_digest_add(&md5, id, idsize); if (crypt->algorithm_revision >= 4 && (crypt->flags & PPCRYPT_NO_METADATA)) - md5add("\xFF\xFF\xFF\xFF", 4); - md5put(crypt->filekey); + md5_digest_add(&md5, "\xFF\xFF\xFF\xFF", 4); + md5_digest_get(&md5, crypt->filekey, MD5_BYTES); if (crypt->algorithm_revision >= 3) { for (i = 0; i < 50; ++i) { - pplib_md5(crypt->filekey, (size_t)crypt->filekeylength, temp); + md5_digest(crypt->filekey, (size_t)crypt->filekeylength, temp, MD5_BYTES); memcpy(crypt->filekey, temp, 16); } } @@ -146,10 +148,11 @@ static void ppcrypt_userkey (ppcrypt *crypt, const void *id, size_t idsize, uint } else { - md5init(); - md5add(padding_string, 32); - md5add(id, idsize); - md5put(password_hash); + md5_state md5; + md5_digest_init(&md5); + md5_digest_add(&md5, padding_string, 32); + md5_digest_add(&md5, id, idsize); + md5_digest_get(&md5, password_hash, MD5_BYTES); rc4_encode_data(password_hash, 16, password_hash, crypt->filekey, crypt->filekeylength); for (i = 1; i <= 19; ++i) { @@ -166,13 +169,13 @@ static void ppcrypt_userkey (ppcrypt *crypt, const void *id, size_t idsize, uint static const uint8_t nulliv[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* AES-256 initialization vector */ -static ppcrypt_status ppcrypt_authenticate_perms (ppcrypt *crypt, ppstring perms) +static ppcrypt_status ppcrypt_authenticate_perms (ppcrypt *crypt, ppstring *perms) { /* decode /Perms string overriding crypt setup (should match anyway) */ uint8_t permsdata[16]; //int64_t p; //int i; - aes_decode_data(perms, ppstring_size(perms), permsdata, crypt->filekey, crypt->filekeylength, nulliv, AES_NULL_PADDING); + aes_decode_data(perms->data, perms->size, permsdata, crypt->filekey, crypt->filekeylength, nulliv, AES_NULL_PADDING); if (permsdata[9] != 'a' || permsdata[10] != 'd' || permsdata[11] != 'b') return PPCRYPT_FAIL; @@ -195,11 +198,11 @@ ppcrypt_status ppdoc_crypt_init (ppdoc *pdf, const void *userpass, size_t userpa ppcrypt *crypt; ppdict *trailer, *encrypt; ppobj *obj; - ppname name, *pkey; - ppstring userkey, ownerkey, userkey_e = NULL, ownerkey_e = NULL; + ppname *name, **pkey; + ppstring *userkey, *ownerkey, *userkey_e = NULL, *ownerkey_e = NULL; size_t hashlength; pparray *idarray; - ppstring id = NULL, perms = NULL; + ppstring *id = NULL, *perms = NULL; int cryptflags, encryptmd; size_t strkeylength, stmkeylength; @@ -240,7 +243,7 @@ ppcrypt_status ppdoc_crypt_init (ppdoc *pdf, const void *userpass, size_t userpa ownerkey = ppstring_decoded(ownerkey); /* for some reason acrobat pads /O and /U to 127 bytes with NULL, so we don't check the exact length but ensure the minimal */ hashlength = crypt->algorithm_variant < 5 ? 32 : 48; - if (ppstring_size(userkey) < hashlength || ppstring_size(ownerkey) < hashlength) + if (userkey->size < hashlength || ownerkey->size < hashlength) return PPCRYPT_FAIL; if (crypt->algorithm_variant < 5) { // get first string from /ID (must not be ref) @@ -254,12 +257,12 @@ ppcrypt_status ppdoc_crypt_init (ppdoc *pdf, const void *userpass, size_t userpa return PPCRYPT_FAIL; userkey_e = ppstring_decoded(userkey_e); ownerkey_e = ppstring_decoded(ownerkey_e); - if (ppstring_size(userkey_e) < 32 || ppstring_size(ownerkey_e) < 32) + if (userkey_e->size < 32 || ownerkey_e->size < 32) return PPCRYPT_FAIL; if ((perms = ppdict_get_string(encrypt, "Perms")) == NULL) return PPCRYPT_FAIL; perms = ppstring_decoded(perms); - if (ppstring_size(perms) != 16) + if (perms->size != 16) return PPCRYPT_FAIL; } @@ -344,46 +347,49 @@ ppcrypt_status ppdoc_crypt_init (ppdoc *pdf, const void *userpass, size_t userpa if (crypt->algorithm_variant < 5) { /* authenticate by comparing a generated vs present /U entry; depending on variant 16 or 32 bytes to compare */ - ppcrypt_filekey(crypt, ownerkey, ppstring_size(ownerkey), id, ppstring_size(id)); - ppcrypt_userkey(crypt, id, ppstring_size(id), password_hash); /* needs file key so comes after key generation */ - if (memcmp(userkey, password_hash, (crypt->algorithm_revision >= 3 ? 16 : 32)) == 0) + ppcrypt_filekey(crypt, ownerkey->data, ownerkey->size, id->data, id->size); + ppcrypt_userkey(crypt, id->data, id->size, password_hash); /* needs file key so comes after key generation */ + if (memcmp(userkey->data, password_hash, (crypt->algorithm_revision >= 3 ? 16 : 32)) == 0) return PPCRYPT_DONE; return PPCRYPT_PASS; } if (crypt->flags & PPCRYPT_USER_PASSWORD) { + sha256_state sha; validation_salt = (uint8_t *)userkey + 32; key_salt = validation_salt + 8; - sha256init(); - sha256add(crypt->userpass, crypt->userpasslength); - sha256add(validation_salt, 8); - sha256put(password_hash); - if (memcmp(userkey, password_hash, 32) != 0) + sha256_digest_init(&sha); + sha256_digest_add(&sha, crypt->userpass, crypt->userpasslength); + sha256_digest_add(&sha, validation_salt, 8); + sha256_digest_get(&sha, password_hash, SHA_BYTES); + if (memcmp(userkey->data, password_hash, 32) != 0) return PPCRYPT_PASS; - sha256init(); - sha256add(crypt->userpass, crypt->userpasslength); - sha256add(key_salt, 8); - sha256put(password_hash); - aes_decode_data(userkey_e, 32, crypt->filekey, password_hash, 32, nulliv, AES_NULL_PADDING); + sha256_digest_init(&sha); + sha256_digest_add(&sha, crypt->userpass, crypt->userpasslength); + sha256_digest_add(&sha, key_salt, 8); + sha256_digest_get(&sha, password_hash, SHA_BYTES); + aes_decode_data(userkey_e->data, 32, crypt->filekey, password_hash, 32, nulliv, AES_NULL_PADDING); return ppcrypt_authenticate_perms(crypt, perms); } if (crypt->flags & PPCRYPT_OWNER_PASSWORD) { + sha256_state sha; validation_salt = (uint8_t *)ownerkey + 32; key_salt = validation_salt + 8; - sha256init(); - sha256add(crypt->ownerpass, crypt->ownerpasslength); - sha256add(validation_salt, 8); - sha256add(userkey, 48); - sha256put(password_hash); - if (memcmp(ownerkey, password_hash, 32) != 0) + + sha256_digest_init(&sha); + sha256_digest_add(&sha, crypt->ownerpass, crypt->ownerpasslength); + sha256_digest_add(&sha, validation_salt, 8); + sha256_digest_add(&sha, userkey, 48); + sha256_digest_get(&sha, password_hash, SHA_BYTES); + if (memcmp(ownerkey->data, password_hash, 32) != 0) return PPCRYPT_PASS; - sha256init(); - sha256add(crypt->ownerpass, crypt->ownerpasslength); - sha256add(key_salt, 8); - sha256add(userkey, 48); - sha256put(password_hash); - aes_decode_data(ownerkey_e, 32, crypt->filekey, password_hash, 32, nulliv, AES_NULL_PADDING); + sha256_digest_init(&sha); + sha256_digest_add(&sha, crypt->ownerpass, crypt->ownerpasslength); + sha256_digest_add(&sha, key_salt, 8); + sha256_digest_add(&sha, userkey, 48); + sha256_digest_get(&sha, password_hash, SHA_BYTES); + aes_decode_data(ownerkey_e->data, 32, crypt->filekey, password_hash, 32, nulliv, AES_NULL_PADDING); return ppcrypt_authenticate_perms(crypt, perms); } return PPCRYPT_FAIL; // should never get here @@ -415,11 +421,11 @@ static void ppcrypt_strkey (ppcrypt *crypt, ppref *ref, int aes) if (crypt->algorithm_variant < 5) { - crypt->filekey[crypt->filekeylength + 0] = get_byte1(ref->number); - crypt->filekey[crypt->filekeylength + 1] = get_byte2(ref->number); - crypt->filekey[crypt->filekeylength + 2] = get_byte3(ref->number); - crypt->filekey[crypt->filekeylength + 3] = get_byte1(ref->version); - crypt->filekey[crypt->filekeylength + 4] = get_byte2(ref->version); + crypt->filekey[crypt->filekeylength + 0] = get_number_byte1(ref->number); + crypt->filekey[crypt->filekeylength + 1] = get_number_byte2(ref->number); + crypt->filekey[crypt->filekeylength + 2] = get_number_byte3(ref->number); + crypt->filekey[crypt->filekeylength + 3] = get_number_byte1(ref->version); + crypt->filekey[crypt->filekeylength + 4] = get_number_byte2(ref->version); if (aes) { @@ -429,7 +435,7 @@ static void ppcrypt_strkey (ppcrypt *crypt, ppref *ref, int aes) crypt->filekey[crypt->filekeylength + 8] = 0x54; } - pplib_md5(crypt->filekey, crypt->filekeylength + (aes ? 9 : 5), crypt->cryptkey); + md5_digest(crypt->filekey, crypt->filekeylength + (aes ? 9 : 5), crypt->cryptkey, MD5_BYTES); crypt->cryptkeylength = crypt->filekeylength + 5 >= 16 ? 16 : crypt->filekeylength + 5; } else @@ -477,26 +483,26 @@ the stream belongs; stream->ref and accessing the crypt info stream->ref->xref-> It would be ok as long as absolutelly nothing happens with ref and crypt. At some point pplib may drift into rewriting support, which would imply ref/xref/crypt/pdf structures modifications. So I feel better with generating a crypt key for every stream in encrypted document, paying a cost -of pplib_md5() for all streams, not necessarily those actually read. +of md5 for all streams, not necessarily those actually read. Key generation is the same as for strings, but different for distinct encryption methods (rc4 vs aes). Since streams and strings might theoretically be encrypted with different filters. No reason to cacche decryption state here. */ -ppstring ppcrypt_stmkey (ppcrypt *crypt, ppref *ref, int aes, ppheap **pheap) +ppstring * ppcrypt_stmkey (ppcrypt *crypt, ppref *ref, int aes, ppheap *heap) { - ppstring cryptkeystring; + ppstring *cryptkeystring; //if (crypt->cryptkeylength > 0) // return; if (crypt->algorithm_variant < 5) { - crypt->filekey[crypt->filekeylength + 0] = get_byte1(ref->number); - crypt->filekey[crypt->filekeylength + 1] = get_byte2(ref->number); - crypt->filekey[crypt->filekeylength + 2] = get_byte3(ref->number); - crypt->filekey[crypt->filekeylength + 3] = get_byte1(ref->version); - crypt->filekey[crypt->filekeylength + 4] = get_byte2(ref->version); + crypt->filekey[crypt->filekeylength + 0] = get_number_byte1(ref->number); + crypt->filekey[crypt->filekeylength + 1] = get_number_byte2(ref->number); + crypt->filekey[crypt->filekeylength + 2] = get_number_byte3(ref->number); + crypt->filekey[crypt->filekeylength + 3] = get_number_byte1(ref->version); + crypt->filekey[crypt->filekeylength + 4] = get_number_byte2(ref->version); if (aes) { @@ -506,7 +512,7 @@ ppstring ppcrypt_stmkey (ppcrypt *crypt, ppref *ref, int aes, ppheap **pheap) crypt->filekey[crypt->filekeylength + 8] = 0x54; } - pplib_md5(crypt->filekey, crypt->filekeylength + (aes ? 9 : 5), crypt->cryptkey); + md5_digest(crypt->filekey, crypt->filekeylength + (aes ? 9 : 5), crypt->cryptkey, MD5_BYTES); crypt->cryptkeylength = crypt->filekeylength + 5 >= 16 ? 16 : crypt->filekeylength + 5; // how about 256bits AES?? } else @@ -514,6 +520,6 @@ ppstring ppcrypt_stmkey (ppcrypt *crypt, ppref *ref, int aes, ppheap **pheap) memcpy(crypt->cryptkey, crypt->filekey, 32); // just for the record crypt->cryptkeylength = 32; } - cryptkeystring = ppstring_internal(crypt->cryptkey, crypt->cryptkeylength, pheap); + cryptkeystring = ppstring_internal(crypt->cryptkey, crypt->cryptkeylength, heap); return ppstring_decoded(cryptkeystring); } diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppcrypt.h b/Build/source/texk/web2c/luatexdir/luapplib/src/ppcrypt.h index ae8cdbdbc60..98864f860c7 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppcrypt.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppcrypt.h @@ -61,7 +61,7 @@ int ppstring_decrypt (ppcrypt *crypt, const void *input, size_t size, void *outp #define ppcrypt_end_ref(crypt) ((crypt)->ref = NULL, (crypt)->cryptkeylength = 0) #define ppcrypt_ref(pdf, crypt) ((crypt = (pdf)->crypt) != NULL && crypt->ref != NULL) -int ppcrypt_type (ppcrypt *crypt, ppname cryptname, ppuint *length, int *cryptflags); -ppstring ppcrypt_stmkey (ppcrypt *crypt, ppref *ref, int aes, ppheap **pheap); +int ppcrypt_type (ppcrypt *crypt, ppname *cryptname, ppuint *length, int *cryptflags); +ppstring * ppcrypt_stmkey (ppcrypt *crypt, ppref *ref, int aes, ppheap *heap); -#endif
\ No newline at end of file +#endif diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppdict.c b/Build/source/texk/web2c/luatexdir/luapplib/src/ppdict.c index f04403d8350..95ea96b9f33 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppdict.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppdict.c @@ -1,42 +1,45 @@ #include "pplib.h" -ppdict * ppdict_create (const ppobj *stackpos, size_t size, ppheap **pheap) -{ - ppdict *dict; - ppobj *data; - ppname *pkey; - size_t i; - size >>= 1; - dict = (ppdict *)ppheap_take(pheap, sizeof(ppdict) + size * sizeof(ppobj) + (size + 1) * sizeof(ppname *)); // ? + size * sizeof(ppdict_map_node) +ppdict * ppdict_create (const ppobj *stackpos, size_t size, ppheap *heap) +{ + ppdict *dict; + ppobj *data; + ppname **pkey; + size_t i; + + size >>= 1; // num of key-value pairs + dict = (ppdict *)ppstruct_take(heap, sizeof(ppdict)); + dict->data = data = (ppobj *)ppstruct_take(heap, size * sizeof(ppobj)); + dict->keys = pkey = (ppname **)ppstruct_take(heap, (size + 1) * sizeof(ppname **)); dict->size = 0; - dict->data = data = (ppobj *)(dict + 1); - dict->keys = pkey = (ppname *)(dict->data + size); - for (i = 0; i < size; ++i, stackpos += 2) - { - if (stackpos->type != PPNAME) // we need this check at lest for trailer hack - continue; + + for (i = 0; i < size; ++i, stackpos += 2) + { + if (stackpos->type != PPNAME) // we need this check at lest for trailer hack + continue; *pkey = stackpos->name; *data = *(stackpos + 1); ++pkey, ++data, ++dict->size; - } - *pkey = NULL; // sentinel for convinient iteration - return dict; + } + *pkey = NULL; // sentinel for convinient iteration + return dict; } ppobj * ppdict_get_obj (ppdict *dict, const char *name) -{ // some lookup? will see - ppname *pkey; +{ + ppname **pkey; ppobj *obj; + for (ppdict_first(dict, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj)) - if (strcmp(*pkey, name) == 0) // not ppname_eq() or ppname_is()!! + if (strcmp((*pkey)->data, name) == 0) // not ppname_eq() or ppname_is()!! return obj; return NULL; } ppobj * ppdict_rget_obj (ppdict *dict, const char *name) { - ppobj *obj; + ppobj *obj; return (obj = ppdict_get_obj(dict, name)) != NULL ? ppobj_rget_obj(obj) : NULL; } @@ -88,25 +91,25 @@ int ppdict_rget_num (ppdict *dict, const char *name, ppnum *v) return (obj = ppdict_get_obj(dict, name)) != NULL ? ppobj_rget_num(obj, *v) : 0; } -ppname ppdict_get_name (ppdict *dict, const char *name) +ppname * ppdict_get_name (ppdict *dict, const char *name) { ppobj *obj; return (obj = ppdict_get_obj(dict, name)) != NULL ? ppobj_get_name(obj) : NULL; } -ppname ppdict_rget_name (ppdict *dict, const char *name) +ppname * ppdict_rget_name (ppdict *dict, const char *name) { ppobj *obj; return (obj = ppdict_get_obj(dict, name)) != NULL ? ppobj_rget_name(obj) : NULL; } -ppstring ppdict_get_string (ppdict *dict, const char *name) +ppstring * ppdict_get_string (ppdict *dict, const char *name) { ppobj *obj; return (obj = ppdict_get_obj(dict, name)) != NULL ? ppobj_get_string(obj) : NULL; } -ppstring ppdict_rget_string (ppdict *dict, const char *name) +ppstring * ppdict_rget_string (ppdict *dict, const char *name) { ppobj *obj; return (obj = ppdict_get_obj(dict, name)) != NULL ? ppobj_rget_string(obj) : NULL; diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppdict.h b/Build/source/texk/web2c/luatexdir/luapplib/src/ppdict.h index 5a808b772c1..b13ff8eb29d 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppdict.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppdict.h @@ -2,6 +2,6 @@ #ifndef PP_DICT_H #define PP_DICT_H -ppdict * ppdict_create (const ppobj *stack, size_t size, ppheap **pheap); +ppdict * ppdict_create (const ppobj *stack, size_t size, ppheap *heap); #endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppfilter.h b/Build/source/texk/web2c/luatexdir/luapplib/src/ppfilter.h index 583aa8cf48f..583aa8cf48f 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppfilter.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppfilter.h diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/ppheap.c b/Build/source/texk/web2c/luatexdir/luapplib/src/ppheap.c new file mode 100644 index 00000000000..f2fbc2b7e4f --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppheap.c @@ -0,0 +1,40 @@ + +#include "pplib.h" + +#define PPBYTES_HEAP_BLOCK 0xFFF +#define PPBYTES_HEAP_LARGE (PPBYTES_HEAP_BLOCK >> 2) +#define PPSTRUCT_HEAP_BLOCK 0xFFF +#define PPSTRUCT_HEAP_LARGE (PPSTRUCT_HEAP_BLOCK >> 2) + +void ppheap_init (ppheap *heap) +{ + ppstruct_heap_init(heap, PPSTRUCT_HEAP_BLOCK, PPSTRUCT_HEAP_LARGE, 0); + ppbytes_heap_init(heap, PPBYTES_HEAP_BLOCK, PPBYTES_HEAP_LARGE, 0); +} + +void ppheap_free (ppheap *heap) +{ + ppstruct_heap_free(heap); + ppbytes_heap_free(heap); +} + +void ppheap_renew (ppheap *heap) +{ + ppstruct_heap_clear(heap); + ppbytes_heap_clear(heap); + ppbytes_buffer_init(heap); +} + +ppbyte * ppbytes_flush (ppheap *heap, iof *O, size_t *psize) +{ + ppbyte *data; + size_t size; + + //ASSERT(&heap->bytesheap == O->link); + iof_put(O, '\0'); + data = (ppbyte *)O->buf; + size = (size_t)iof_size(O); + ppbytes_heap_done(heap, data, size); + *psize = size - 1; + return data; +}
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/ppheap.h b/Build/source/texk/web2c/luatexdir/luapplib/src/ppheap.h new file mode 100644 index 00000000000..1d6559d93c0 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppheap.h @@ -0,0 +1,46 @@ + +#ifndef PP_HEAP_H +#define PP_HEAP_H + +#include "utilmem.h" + +#define pp_malloc util_malloc +//#define pp_callic util_calloc +//#define pp_realloc util_realloc +#define pp_free util_free + +#include "utilmemheapiof.h" +//#include "utilmeminfo.h" + +#define ppbytes_heap heap16 +#define ppbytes_heap_init(heap, space, large, flags) (heap16_init(&(heap)->bytesheap, space, large, flags), heap16_head(&(heap)->bytesheap)) +//#define ppbytes_heap_some(heap, size, pspace) _heap16_some(&(heap)->bytesheap, size, pspace) +#define ppbytes_heap_done(heap, data, written) heap16_done(&(heap)->bytesheap, data, written) +#define ppbytes_heap_clear(heap) heap16_clear(&(heap)->bytesheap) +#define ppbytes_heap_free(heap) heap16_free(&(heap)->bytesheap) +#define ppbytes_heap_info(heap, info, append) heap16_stats(&(heap)->bytesheap, info, append) + +#define ppbytes_take(heap, size) _heap16_take(&(heap)->bytesheap, size) +#define ppbytes_buffer_init(heap) heap16_buffer_init(&(heap)->bytesheap, &(heap)->bytesbuffer) +#define ppbytes_buffer(heap, atleast) heap16_buffer_some(&(heap)->bytesheap, &(heap)->bytesbuffer, atleast) + +#define ppstruct_heap heap64 +#define ppstruct_heap_init(heap, space, large, flags) (heap64_init(&(heap)->structheap, space, large, flags), heap64_head(&(heap)->structheap)) +#define ppstruct_heap_clear(heap) heap64_clear(&(heap)->structheap) +#define ppstruct_heap_free(heap) heap64_free(&(heap)->structheap) +#define ppstruct_heap_info(heap, info, append) heap64_stats(&(heap)->structheap, info, append) +#define ppstruct_take(heap, size) _heap64_take(&(heap)->structheap, size) + +typedef struct { + ppbytes_heap bytesheap; + ppstruct_heap structheap; + iof bytesbuffer; +} ppheap; + +ppbyte * ppbytes_flush (ppheap *heap, iof *O, size_t *psize); + +void ppheap_init (ppheap *heap); +void ppheap_free (ppheap *heap); +void ppheap_renew (ppheap *heap); + +#endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/pplib.h b/Build/source/texk/web2c/luatexdir/luapplib/src/pplib.h index a3bf1eb180a..e753cfa0514 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/pplib.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/pplib.h @@ -9,7 +9,6 @@ #include "utiliof.h" #include "utillog.h" -#include "utilarm.h" #include "ppapi.h" #include "ppheap.h" diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppload.c b/Build/source/texk/web2c/luatexdir/luapplib/src/ppload.c index f51f7a5db68..0e72039d84f 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppload.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppload.c @@ -1,6 +1,4 @@ -#include <utilbasexx.h> - #include "pplib.h" const char * ppobj_kind[] = { "none", "null", "bool", "integer", "number", "name", "string", "array", "dict", "stream", "ref" }; @@ -18,21 +16,29 @@ const char * ppobj_kind[] = { "none", "null", "bool", "integer", "number", "name static const char * ppref_str (ppuint refnumber, ppuint refversion) { - static char buffer[MAX_INT_DIGITS + 1 + MAX_INT_DIGITS + 1 + 1 + 1]; -#if defined(MSVC64)|| defined(MINGW64) - sprintf(buffer, PPUINTF " " PPUINTF " R", refnumber, refversion); -#else - sprintf(buffer, PPUINTF " " PPUINTF " R", (unsigned long)(refnumber), (unsigned long)(refversion)); -#endif - return buffer; + static char buffer[MAX_INT_DIGITS + 1 + MAX_INT_DIGITS + 1 + 1 + 1]; + sprintf(buffer, "%lu %lu R", (unsigned long)(refnumber), (unsigned long)(refversion)); + return buffer; } /* name */ +/* +pdf spec page 57: +"The name may include any regular characters, but not delimiter or white-space characters (see Section 3.1, “Lexical Conventions”)." +"The token / (a slash followed by no regular characters) is a valid name" +"Beginning with PDF 1.2, any character except null (character code 0) may be included in a name by writing its 2-digit hexadecimal code, +preceded by the number sign character (#); see implementation notes 3 and 4 in Appendix H. This syntax is required to represent any of the +delimiter or white-space characters or the number sign character itself; it is recommended but not required for characters whose codes +are outside the range 33 (!) to 126 (~)." + +This suggests we should accept bytes 128..255 as a part of the name. +*/ + // pdf name delimiters: 0..32, ()<>[]{}/% // # treated specially // .+- are valid part of name; keep in mind names such as -| | |- .notdef ABCDEF+Font etc. -const char ppname_byte_lookup[] = { +static const int8_t ppname_byte_lookup[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, '#', 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, @@ -51,269 +57,213 @@ const char ppname_byte_lookup[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; -#define PPNAME_INIT (8+1) - -#define ppname_flush(O, ghost, siz, flgs) \ - (iof_put(O, '\0'), \ - ghost = (_ppname *)ppheap_flush(O, &siz), \ - ghost->flags = flgs, \ - ghost->size = siz - sizeof(_ppname) - 1, \ - (ppname)(ghost + 1)) - -#if ARM_COMPLAINT -#define ppname_flush_with_ego(O, ghost, siz, flgs) \ - (iof_put(O, '\0'), \ - pad=(O->pos - pos_begin)%(sizeof(ppname*)), \ - iof_ensure(O, pad+sizeof(ppname *)), \ - O->pos += sizeof(ppname *), \ - O->pos += pad, \ - ghost = (_ppname *)ppheap_flush(O, &siz), \ - ghost->flags = flgs, \ - ghost->size = siz - sizeof(_ppname) - 1 - pad - sizeof(ppname *), \ - (ppname)(ghost + 1)) -#else -#define ppname_flush_with_ego(O, ghost, siz, flgs) \ - (iof_put(O, '\0'), \ - iof_ensure(O, sizeof(ppname *)), \ - O->pos += sizeof(ppname *), \ - ghost = (_ppname *)ppheap_flush(O, &siz), \ - ghost->flags = flgs, \ - ghost->size = siz - sizeof(_ppname) - 1 - sizeof(ppname *), \ - (ppname)(ghost + 1)) -#endif - -#if ARM_COMPLIANT -#define ppname_set_alter_ego(name, ghost, ego) do{ \ - size_t t = ((ghost)->size + 1); \ - t = (t%sizeof(ppname *))==0?t: (t/sizeof(ppname *)+1)*sizeof(ppname *); \ - (*((ppname *)(name + t)) = ego); \ -}while(0) -#else -#define ppname_set_alter_ego(name, ghost, ego) (*((ppname *)(name + (ghost)->size + 1)) = ego) -#endif - -#if ARM_COMPLIANT -#define ppname_get_alter_ego(name) (*((ppname *)((name + (ppname_size(name)+1)%sizeof(ppname *) == 0 ? (ppname_size(name)+1) : ( (ppname_size(name)+1)/sizeof(ppname *) + 1 )*sizeof(ppname *) )))) -#else -#define ppname_get_alter_ego(name) (*((ppname *)(name + ppname_size(name) + 1))) -#endif - - - -static ppname ppscan_name (iof *I, ppheap **pheap) -{ - int c, decode; +/* +20190827: The end of the name is any byte with 0 lookup value. When reading a ref object or objstm stream containing +a single name, we may get input byte IOFEOF (-1), which must not be treated as 255. So a check for (c >= 0) is needed, +otherwise we keep writing byte 255 to the output buffer until not enough memory. +*/ + +#define ppnamebyte(c) (c >= 0 && ppname_byte_lookup[(uint8_t)(c)]) + +static const int8_t pphex_byte_lookup[] = { + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, + -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 +}; + +/* no need for (c >= 0) check here */ + +#define pphex(c) pphex_byte_lookup[(uint8_t)(c)] + +#define PPNAME_INIT (7 + 1) + +static ppname * ppscan_name (iof *I, ppheap *heap) +{ + ppname *encoded, *decoded; iof *O; - _ppname *ghost1, *ghost2; - ppname encoded, decoded; - size_t size; - const char *p, *e; - uint8_t v1, v2; -#if ARM_COMPLIANT - ptrdiff_t pad; - uint8_t* pos_begin; -#endif - - O = ppheap_buffer(pheap, sizeof(_ppname), PPNAME_INIT); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - for (decode = 0, c = iof_char(I); c >= 0 && ppname_byte_lookup[c]; c = iof_next(I)) + int decode, c; + uint8_t *p, *e; + int8_t h1, h2; + + O = ppbytes_buffer(heap, PPNAME_INIT); + for (decode = 0, c = iof_char(I); ppnamebyte(c); c = iof_next(I)) { - if (c == '#') - decode = 1; + if (c == '#') decode = 1; iof_put(O, c); } - if (!decode) - return ppname_flush(O, ghost1, size, 0); - encoded = ppname_flush_with_ego(O, ghost1, size, 0|PPNAME_ENCODED); - O = ppheap_buffer(pheap, sizeof(_ppname), PPNAME_INIT); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - for (p = encoded, e = encoded + ghost1->size; p < e; ++p) + encoded = (ppname *)ppstruct_take(heap, sizeof(ppname)); + encoded->data = ppbytes_flush(heap, O, &encoded->size); + if (decode) { - if (*p == '#' && p + 2 < e) { - v1 = base16_value(p[1]); - v2 = base16_value(p[2]); - iof_put(O, ((v1<<4)+v2)); - p += 2; + O = ppbytes_buffer(heap, encoded->size); // decoded always a bit smaller + for (p = (uint8_t *)encoded->data, e = p + encoded->size; p < e; ++p) + { + if (*p == '#' && p + 2 < e && (h1 = pphex(p[1])) >= 0 && (h2 = pphex(p[2])) >= 0) + { + iof_set(O, ((h1 << 4)|h2)); + p += 2; + } + else + iof_set(O, *p); } - else - iof_put(O, *p); + decoded = (ppname *)ppstruct_take(heap, sizeof(ppname)); + decoded->data = ppbytes_flush(heap, O, &decoded->size); + encoded->flags = PPNAME_ENCODED; + decoded->flags = PPNAME_DECODED; + encoded->alterego = decoded, decoded->alterego = encoded; + } + else + { + encoded->flags = 0; + encoded->alterego = encoded; } - decoded = ppname_flush_with_ego(O, ghost2, size, 0|PPNAME_DECODED); - ppname_set_alter_ego(encoded, ghost1, decoded); - ppname_set_alter_ego(decoded, ghost2, encoded); return encoded; } -static ppname ppscan_exec (iof *I, ppheap **pheap, int first) +static ppname * ppscan_exec (iof *I, ppheap *heap, uint8_t firstbyte) { - int c, decode; + ppname *encoded, *decoded; iof *O; - _ppname *ghost1, *ghost2; - ppname encoded, decoded; - size_t size; - const char *p, *e; - uint8_t v1, v2; -#if ARM_COMPLIANT - ptrdiff_t pad; - uint8_t* pos_begin; -#endif - O = ppheap_buffer(pheap, sizeof(_ppname), PPNAME_INIT); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - iof_put(O, first); - for (decode = 0, c = iof_char(I); c >= 0 && ppname_byte_lookup[c]; c = iof_next(I)) + int decode, c; + uint8_t *p, *e; + int8_t h1, h2; + + O = ppbytes_buffer(heap, PPNAME_INIT); + iof_put(O, firstbyte); + for (decode = 0, c = iof_char(I); ppnamebyte(c); c = iof_next(I)) { - if (c == '#') - decode = 1; + if (c == '#') decode = 1; iof_put(O, c); } - if (!decode) - return ppname_flush(O, ghost1, size, PPNAME_EXEC); - encoded = ppname_flush_with_ego(O, ghost1, size, PPNAME_EXEC|PPNAME_ENCODED); - O = ppheap_buffer(pheap, sizeof(_ppname), PPNAME_INIT); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - for (p = encoded, e = encoded + ghost1->size; p < e; ++p) + encoded = (ppname *)ppstruct_take(heap, sizeof(ppname)); + encoded->data = ppbytes_flush(heap, O, &encoded->size); + if (decode) { - if (*p == '#' && p + 2 < e) { - v1 = base16_value(p[1]); - v2 = base16_value(p[2]); - iof_put(O, ((v1<<4)+v2)); - p += 2; + O = ppbytes_buffer(heap, encoded->size); + for (p = (uint8_t *)encoded->data, e = p + encoded->size; p < e; ++p) + { + if (*p == '#' && p + 2 < e && (h1 = pphex(p[1])) >= 0 && (h2 = pphex(p[2])) >= 0) + { + iof_set(O, ((h1 << 4)|h2)); + p += 2; + } + else + iof_set(O, *p); } - else - iof_put(O, *p); + decoded = (ppname *)ppstruct_take(heap, sizeof(ppname)); + decoded->data = ppbytes_flush(heap, O, &decoded->size); + encoded->flags = PPNAME_EXEC|PPNAME_ENCODED; + decoded->flags = PPNAME_EXEC|PPNAME_DECODED; + encoded->alterego = decoded, decoded->alterego = encoded; + } + else + { + encoded->flags = PPNAME_EXEC; + encoded->alterego = encoded; } - decoded = ppname_flush_with_ego(O, ghost2, size, PPNAME_EXEC|PPNAME_DECODED); - ppname_set_alter_ego(encoded, ghost1, decoded); - ppname_set_alter_ego(decoded, ghost2, encoded); return encoded; } -static ppname ppexec_internal (const void *data, size_t size, ppheap **pheap) -{ // used only for artificial 'EI' operator name - iof *O; - _ppname *ghost1; - - O = ppheap_buffer(pheap, sizeof(_ppname), size); - iof_write(O, data, size); - return ppname_flush(O, ghost1, size, PPNAME_EXEC); +static ppname * ppname_internal (const void *data, size_t size, int flags, ppheap *heap) +{ // so far needed only for 'EI' operator + ppname *encoded; + encoded = (ppname *)ppstruct_take(heap, sizeof(ppname)); + encoded->data = (ppbyte *)ppbytes_take(heap, size + 1); + memcpy(encoded->data, data, size); + encoded->data[size] = '\0'; + encoded->size = size; + encoded->alterego = encoded; + encoded->flags = flags; + return encoded; } -ppname ppname_decoded (ppname name) +#define ppexec_internal(data, size, heap) ppname_internal(data, size, PPNAME_EXEC, heap) + +ppname * ppname_decoded (ppname *name) { - const _ppname *ghost; - ghost = _ppname_ghost(name); - return (ghost->flags & PPNAME_ENCODED) ? ppname_get_alter_ego(name) : name; + return (name->flags & PPNAME_ENCODED) ? name->alterego : name; } -ppname ppname_encoded (ppname name) +ppname * ppname_encoded (ppname *name) { - const _ppname *ghost; - ghost = _ppname_ghost(name); - return (ghost->flags & PPNAME_DECODED) ? ppname_get_alter_ego(name) : name; + return (name->flags & PPNAME_DECODED) ? name->alterego : name; } -/* string */ - -#define PPSTRING_INIT (16+1) - -#define ppstring_flush(O, ghost, siz, flgs) \ - (iof_put(O, '\0'), \ - ghost = (_ppstring *)ppheap_flush(O, &siz), \ - ghost->flags = flgs, \ - ghost->size = siz - sizeof(_ppstring) - 1, \ - (ppstring)(ghost + 1)) - -#if ARM_COMPLAINT -#define ppstring_flush_with_ego(O, ghost, siz, flgs) \ - (iof_put(O, '\0'), \ - pad=(O->pos - pos_begin)%(sizeof(ppstring*)), \ - iof_ensure(O, pad+sizeof(ppstring *)), \ - O->pos += sizeof(ppstring *), \ - O->pos += pad, \ - ghost = (_ppstring *)ppheap_flush(O, &siz), \ - ghost->flags = flgs, \ - ghost->size = siz - sizeof(_ppstring) - 1 - pad - sizeof(ppstring *), \ - (ppstring)(ghost + 1)) -#else -#define ppstring_flush_with_ego(O, ghost, siz, flgs) \ - (iof_put(O, '\0'), \ - iof_ensure(O, sizeof(ppstring *)), \ - O->pos += sizeof(ppstring *), \ - ghost = (_ppstring *)ppheap_flush(O, &siz), \ - ghost->flags = flgs, \ - ghost->size = siz - sizeof(_ppstring) - 1 - sizeof(ppstring *), \ - (ppstring)(ghost + 1)) -#endif - -#define ppstring_utf16be_bom(decoded) (decoded[0] == ((char)0xFE) && decoded[1] == ((char)0xFF) ) -#define ppstring_utf16le_bom(decoded) (decoded[0] == ((char)0xFF) && decoded[1] == ((char)0xFE)) - -#define ppstring_check_bom(decoded, ghost) ((void)\ - (ghost->size >= 2 ? (ppstring_utf16be_bom(decoded) ? (ghost->flags |= PPSTRING_UTF16BE) : \ - (ppstring_utf16le_bom(decoded) ? (ghost->flags |= PPSTRING_UTF16LE) : 0)) : 0)) +ppbyte * ppname_decoded_data (ppname *name) +{ + return (name->flags & PPNAME_ENCODED) ? name->alterego->data : name->data; +} -#define ppstring_check_bom2(decoded, ghost1, ghost2) ((void)\ - (ghost2->size >= 2 ? (ppstring_utf16be_bom(decoded) ? ((ghost1->flags |= PPSTRING_UTF16BE), (ghost2->flags |= PPSTRING_UTF16BE)) : \ - (ppstring_utf16le_bom(decoded) ? ((ghost1->flags |= PPSTRING_UTF16LE), (ghost2->flags |= PPSTRING_UTF16LE)) : 0)) : 0)) +ppbyte * ppname_encoded_data (ppname *name) +{ + return (name->flags & PPNAME_DECODED) ? name->alterego->data : name->data; +} +/* string */ +static const int8_t ppstring_byte_escape[] = { /* -1 escaped with octal, >0 escaped with \\, 0 left intact*/ + -1,-1,-1,-1,-1,-1,-1,-1,'b','t','n',-1,'f','r',-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 0, 0, 0, 0, 0, 0, 0, 0,'(',')', 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 +}; -#if ARM_COMPLIANT -#define ppstring_set_alter_ego(string, ghost, ego) do{ \ - size_t t = ((ghost)->size + 1); \ - t = (t%sizeof(ppstring *))==0?t: (t/sizeof(ppstring *)+1)*sizeof(ppstring *); \ - (*((ppstring *)(string + t)) = ego); \ -}while(0) -#else -#define ppstring_set_alter_ego(string, ghost, ego) (*((ppstring *)((string + (ghost)->size + 1))) = ego) -#endif +//// pp string +#define PPSTRING_INIT (7 + 1) -#if ARM_COMPLIANT -#define ppstring_get_alter_ego(string) (*((ppstring *)((string + (ppstring_size(string)+1)%sizeof(ppstring *) == 0 ? (ppstring_size(string)+1) : ( (ppstring_size(string)+1)/sizeof(ppstring *) + 1 )*sizeof(ppstring *) )))) -#else -#define ppstring_get_alter_ego(string) (*((ppstring *)(string + ppstring_size(string) + 1))) -#endif +#define ppstring_check_bom(decoded) ((void)\ + (decoded->size >= 2 ? (ppstring_utf16be_bom(decoded->data) ? (decoded->flags |= PPSTRING_UTF16BE) : \ + (ppstring_utf16le_bom(decoded->data) ? (decoded->flags |= PPSTRING_UTF16LE) : 0)) : 0)) +#define ppstring_check_bom2(decoded, encoded) ((void)\ + (decoded->size >= 2 ? (ppstring_utf16be_bom(decoded->data) ? ((decoded->flags |= PPSTRING_UTF16BE), (encoded->flags |= PPSTRING_UTF16BE)) : \ + (ppstring_utf16le_bom(decoded->data) ? ((decoded->flags |= PPSTRING_UTF16LE), (encoded->flags |= PPSTRING_UTF16LE)) : 0)) : 0)) +#define ppstring_utf16be_bom(data) (data[0] == '\xFE' && data[1] == '\xFF') +#define ppstring_utf16le_bom(data) (data[0] == '\xFF' && data[1] == '\xFE') +#define ppstringesc(c) ppstring_byte_escape[(uint8_t)(c)] -static ppstring ppscan_string (iof *I, ppheap **pheap) +static ppstring * ppscan_string (iof *I, ppheap *heap) { - int c, decode, balance; + ppstring *encoded, *decoded; iof *O; - _ppstring *ghost1, *ghost2; + int c, decode, balance; uint8_t *p, *e; - ppstring encoded, decoded; - size_t size; -#if ARM_COMPLIANT - ptrdiff_t pad; - uint8_t* pos_begin; -#endif - - O = ppheap_buffer(pheap, sizeof(_ppstring), PPSTRING_INIT); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif + + O = ppbytes_buffer(heap, PPSTRING_INIT); for (decode = 0, balance = 0, c = iof_char(I); c >= 0; ) { switch (c) { case '\\': - decode = 1; // unescaping later + decode = 1; iof_put(O, '\\'); if ((c = iof_next(I)) >= 0) { @@ -342,232 +292,280 @@ static ppstring ppscan_string (iof *I, ppheap **pheap) c = iof_next(I); } } - if (!decode) + encoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring)); + encoded->data = ppbytes_flush(heap, O, &encoded->size); + if (decode) { - encoded = ppstring_flush(O, ghost1, size, 0); - ppstring_check_bom(encoded, ghost1); // any bytes can be there - return encoded; - } - encoded = ppstring_flush_with_ego(O, ghost1, size, 0|PPSTRING_ENCODED); - O = ppheap_buffer(pheap, sizeof(_ppstring), PPSTRING_INIT); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - for (p = (uint8_t *)encoded, e = (uint8_t *)encoded + ghost1->size; p < e; ++p) - { - if (*p == '\\') + O = ppbytes_buffer(heap, encoded->size); // decoded can only be smaller + for (p = (uint8_t *)encoded->data, e = p + encoded->size; p < e; ++p) { - if (++p >= e) - break; - switch (*p) + if (*p == '\\') { - case OCTAL_CHAR_CASE: - c = *p - '0'; - if (++p < e && *p >= '0' && *p <= '7') - { - c = (c << 3) + *p - '0'; + if (++p >= e) + break; + switch (*p) + { + case OCTAL_CHAR_CASE: + c = *p - '0'; if (++p < e && *p >= '0' && *p <= '7') + { c = (c << 3) + *p - '0'; - } - iof_put(O, c); - break; - case 'n': - iof_put(O, '\n'); - break; - case 'r': - iof_put(O, '\r'); - break; - case 't': - iof_put(O, '\t'); - break; - case 'b': - iof_put(O, '\b'); - break; - case 'f': - iof_put(O, '\f'); - break; - case NEWLINE_CHAR_CASE: // not a part of the string, ignore (pdf spec page 55) - break; - case '(': case ')': case '\\': - default: // for enything else backslash is ignored (pdf spec page 54) - iof_put(O, *p); - break; + if (++p < e && *p >= '0' && *p <= '7') + c = (c << 3) + *p - '0'; + } + iof_set(O, c); + break; + case 'n': + iof_set(O, '\n'); + break; + case 'r': + iof_set(O, '\r'); + break; + case 't': + iof_set(O, '\t'); + break; + case 'b': + iof_set(O, '\b'); + break; + case 'f': + iof_set(O, '\f'); + break; + case NEWLINE_CHAR_CASE: // not a part of the string, ignore (pdf spec page 55) + break; + case '(': case ')': case '\\': + default: // for anything else backslash is ignored (pdf spec page 54) + iof_set(O, *p); + break; + } } + else + iof_set(O, *p); } - else - iof_put(O, *p); + decoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring)); + decoded->data = ppbytes_flush(heap, O, &decoded->size); + encoded->flags = PPSTRING_ENCODED; + decoded->flags = PPSTRING_DECODED; + encoded->alterego = decoded, decoded->alterego = encoded; + ppstring_check_bom2(decoded, encoded); + } + else + { + encoded->flags = 0; + encoded->alterego = encoded; + ppstring_check_bom(encoded); } - decoded = ppstring_flush_with_ego(O, ghost2, size, 0|PPSTRING_DECODED); - ppstring_check_bom2(decoded, ghost1, ghost2); - ppstring_set_alter_ego(encoded, ghost1, decoded); - ppstring_set_alter_ego(decoded, ghost2, encoded); return encoded; } -/* Hex string may contain white characters. If odd number of digits, the last assumed to be '0' */ - -static ppstring ppscan_base16 (iof *I, ppheap **pheap) +static ppstring * ppscan_base16 (iof *I, ppheap *heap) { - int c, v1, v2; + ppstring *encoded, *decoded; iof *O; - _ppstring *ghost1, *ghost2; - size_t size; - ppstring encoded, decoded; + int c; uint8_t *p, *e; -#if ARM_COMPLIANT - ptrdiff_t pad; - uint8_t* pos_begin; -#endif - O = ppheap_buffer(pheap, sizeof(_ppstring), PPSTRING_INIT); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - for (c = iof_char(I); c >= 0 && (base16_digit(c) || ignored_char(c)); c = iof_next(I)) + int8_t h1, h2; + + O = ppbytes_buffer(heap, PPSTRING_INIT); + for (c = iof_char(I); (pphex(c) >= 0 || ignored_char(c)); c = iof_next(I)) iof_put(O, c); if (c == '>') ++I->pos; - encoded = ppstring_flush_with_ego(O, ghost1, size, PPSTRING_BASE16|PPSTRING_ENCODED); - O = ppheap_buffer(pheap, sizeof(_ppstring), (ghost1->size >> 1) + 1); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - for (p = (uint8_t *)encoded, e = (uint8_t *)encoded + ghost1->size; p < e; ++p) + encoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring)); + encoded->data = ppbytes_flush(heap, O, &encoded->size); + + O = ppbytes_buffer(heap, ((encoded->size + 1) >> 1) + 1); // decoded can only be smaller + for (p = (uint8_t *)encoded->data, e = p + encoded->size; p < e; ++p) { - if ((v1 = base16_value(*p)) < 0) // ignored + if ((h1 = pphex(*p)) < 0) // ignored continue; - for (v2 = 0, ++p; p < e && (v2 = base16_value(*p)) < 0; ++p); - iof_put(O, (v1<<4)|v2); + for (h2 = 0, ++p; p < e && (h2 = pphex(*p)) < 0; ++p); + iof_set(O, (h1 << 4)|h2); } - decoded = ppstring_flush_with_ego(O, ghost2, size, 0|PPSTRING_DECODED); - ppstring_check_bom2(decoded, ghost1, ghost2); - ppstring_set_alter_ego(encoded, ghost1, decoded); - ppstring_set_alter_ego(decoded, ghost2, encoded); + decoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring)); + decoded->data = ppbytes_flush(heap, O, &decoded->size); + + encoded->flags = PPSTRING_BASE16|PPSTRING_ENCODED; + decoded->flags = PPSTRING_BASE16|PPSTRING_DECODED; + encoded->alterego = decoded, decoded->alterego = encoded; + + ppstring_check_bom2(decoded, encoded); + return encoded; +} + +static ppstring * ppstring_buffer (iof *O, ppheap *heap) +{ + ppstring *encoded, *decoded; + uint8_t *p, *e; + + decoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring)); + decoded->data = ppbytes_flush(heap, O, &decoded->size); + + O = ppbytes_buffer(heap, (decoded->size << 1) + 1); // the exact size known + for (p = (uint8_t *)decoded->data, e = p + decoded->size; p < e; ++p) + iof_set2(O, base16_uc_alphabet[(*p) >> 4], base16_uc_alphabet[(*p) & 0xF]); + encoded = ppstruct_take(heap, sizeof(ppstring)); + encoded->data = ppbytes_flush(heap, O, &encoded->size); + encoded->flags = PPSTRING_BASE16|PPSTRING_ENCODED; + decoded->flags = PPSTRING_BASE16|PPSTRING_DECODED; + encoded->alterego = decoded, decoded->alterego = encoded; + // ppstring_check_bom2(decoded, encoded); // ? return encoded; } -/* internal use only; binary string */ - -static ppstring ppstring_buffer (iof *O, ppheap **pheap) -{ - _ppstring *ghost1, *ghost2; - ppstring encoded, decoded; - uint8_t *p, *e; - size_t size; -#if ARM_COMPLIANT - ptrdiff_t pad; - uint8_t* pos_begin; -#endif -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - decoded = ppstring_flush_with_ego(O, ghost2, size, 0|PPSTRING_DECODED); - O = ppheap_buffer(pheap, sizeof(_ppstring), (ghost2->size << 1) + 1); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - for (p = (uint8_t *)decoded, e = (uint8_t *)decoded + ghost2->size; p < e; ++p) - iof_set2(O, base16_uc_alphabet[(*p)>>4], base16_uc_alphabet[(*p)&15]); - encoded = ppstring_flush_with_ego(O, ghost1, size, PPSTRING_BASE16|PPSTRING_ENCODED); - ppstring_set_alter_ego(encoded, ghost1, decoded); - ppstring_set_alter_ego(decoded, ghost2, encoded); - return encoded; -} - -ppstring ppstring_internal (const void *data, size_t size, ppheap **pheap) +ppstring * ppstring_internal (const void *data, size_t size, ppheap *heap) { // so far used only for crypt key iof *O; + O = ppbytes_buffer(heap, size); + memcpy(O->buf, data, size); + O->pos = O->buf + size; + return ppstring_buffer(O, heap); +} + +/* base85; local function for that to make that part independent from utilbasexx */ + +static const int8_t ppstring_base85_lookup[] = { + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, + 15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30, + 31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46, + 47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62, + 63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78, + 79,80,81,82,83,84,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 +}; - O = ppheap_buffer(pheap, sizeof(_ppstring), size); - iof_write(O, data, size); - return ppstring_buffer(O, pheap); -} +#define base85_value(c) ppstring_base85_lookup[(uint8_t)(c)] -/* PDF spec says nothing about base85 strings, but streams might be (afair no leading '<~' but present trailing '~>') */ +#define base85_code(c1, c2, c3, c4, c5) ((((c1 * 85 + c2) * 85 + c3) * 85 + c4) * 85 + c5) +#define base85_eof(c) (c == '~' || c < 0) -static ppstring ppscan_base85 (iof *I, ppheap **pheap) -{ // bawse85 alphabet is 33.117, adobe also hires 'z' and 'y' for compression - int c; +static iof_status ppscan_base85_decode (iof *I, iof *O) +{ + int c1, c2, c3, c4, c5; + uint32_t code; + while (iof_ensure(O, 4)) + { + do { c1 = iof_get(I); } while (ignored_char(c1)); + if (base85_eof(c1)) + return IOFEOF; + switch (c1) + { + case 'z': + iof_set4(O, '\0', '\0', '\0', '\0'); + continue; + case 'y': + iof_set4(O, ' ', ' ', ' ', ' '); + continue; + } + do { c2 = iof_get(I); } while (ignored_char(c2)); + if (base85_eof(c2)) + return IOFERR; + do { c3 = iof_get(I); } while (ignored_char(c3)); + if (base85_eof(c3)) + { + if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0) + return IOFERR; + code = base85_code(c1, c2, 84, 84, 84); /* padding with 'u' (117); 117-33 = 84 */ + iof_set(O, (code >> 24)); + return IOFEOF; + } + do { c4 = iof_get(I); } while (ignored_char(c4)); + if (base85_eof(c4)) + { + if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0 || (c3 = base85_value(c3)) < 0) + return IOFERR; + code = base85_code(c1, c2, c3, 84, 84); + iof_set2(O, code>>24, ((code>>16) & 0xff)); + return IOFEOF; + } + do { c5 = iof_get(I); } while (ignored_char(c5)); + if (base85_eof(c5)) + { + if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0 || + (c3 = base85_value(c3)) < 0 || (c4 = base85_value(c4)) < 0) + return IOFERR; + code = base85_code(c1, c2, c3, c4, 84); + iof_set3(O, (code >> 24), ((code >> 16) & 0xff), ((code >> 8) & 0xff)); + return IOFEOF; + } + if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0 || (c3 = base85_value(c3)) < 0 || + (c4 = base85_value(c4)) < 0 || (c5 = base85_value(c5)) < 0) + return IOFERR; + code = base85_code(c1, c2, c3, c4, c5); + iof_set4(O, (code >> 24), ((code >> 16) & 0xff), ((code >> 8) & 0xff), (code & 0xff)); + } + return IOFFULL; +} + +static ppstring * ppscan_base85 (iof *I, ppheap *heap) +{ // base85 alphabet is 33..117, adobe also hires 'z' and 'y' for compression + ppstring *encoded, *decoded; iof *O, B; - _ppstring *ghost1, *ghost2; - size_t size; - ppstring encoded, decoded; -#if ARM_COMPLIANT - ptrdiff_t pad; - uint8_t* pos_begin; -#endif - O = ppheap_buffer(pheap, sizeof(_ppstring), PPSTRING_INIT); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif + int c; + + O = ppbytes_buffer(heap, PPSTRING_INIT); for (c = iof_char(I); (c >= '!' && c <= 'u') || c == 'z' || c == 'y'; c = iof_next(I)) iof_put(O, c); if (c == '~') if ((c = iof_next(I)) == '>') ++I->pos; - encoded = ppstring_flush_with_ego(O, ghost1, size, PPSTRING_BASE85|PPSTRING_ENCODED); - iof_string_reader(&B, encoded, ghost1->size); - O = ppheap_buffer(pheap, sizeof(_ppstring), (ghost1->size * 5 / 4) + 1); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - base85_decode(&B, O); - decoded = ppstring_flush_with_ego(O, ghost2, size, 0|PPSTRING_DECODED); - ppstring_check_bom2(decoded, ghost1, ghost2); - ppstring_set_alter_ego(encoded, ghost1, decoded); - ppstring_set_alter_ego(decoded, ghost2, encoded); + encoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring)); + encoded->data = ppbytes_flush(heap, O, &encoded->size); + + iof_string_reader(&B, encoded->data, encoded->size); + O = ppbytes_buffer(heap, (encoded->size * 5 / 4) + 1); // may be larger that that because of 'z' and 'y' + ppscan_base85_decode(&B, O); + decoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring)); + decoded->data = ppbytes_flush(heap, O, &decoded->size); + + encoded->flags = PPSTRING_BASE85|PPSTRING_ENCODED; + decoded->flags = PPSTRING_BASE85|PPSTRING_DECODED; + encoded->alterego = decoded, decoded->alterego = encoded; + + ppstring_check_bom2(decoded, encoded); return encoded; } -/* -Encrypted strings. In case of encrypted strings, we first need to decode the string (saving original form hardly makes sense), -then decrypt the string, and encode it again. -*/ +ppstring * ppstring_decoded (ppstring *string) +{ + return (string->flags & PPSTRING_ENCODED) ? string->alterego : string; +} -const char ppstring_byte_escape[] = { /* -1 escaped with octal, >0 escaped with \\, 0 left intact*/ - -1,-1,-1,-1,-1,-1,-1,-1,'b','t','n',-1,'f','r',-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - 0, 0, 0, 0, 0, 0, 0, 0,'(',')', 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 -}; +ppstring * ppstring_encoded (ppstring *string) +{ + return (string->flags & PPSTRING_DECODED) ? string->alterego : string; +} +ppbyte * ppstring_decoded_data (ppstring *string) +{ + return (string->flags & PPSTRING_ENCODED) ? string->alterego->data : string->data; +} -static ppstring ppscan_crypt_string (iof *I, ppcrypt *crypt, ppheap **pheap) +ppbyte * ppstring_encoded_data (ppstring *string) { - int c, b, balance, encode; + return (string->flags & PPSTRING_DECODED) ? string->alterego->data : string->data; +} + + +/* encrypted string */ + +static ppstring * ppscan_crypt_string (iof *I, ppcrypt *crypt, ppheap *heap) +{ + ppstring *encoded, *decoded; iof *O; - _ppstring *ghost1, *ghost2; - ppstring encoded, decoded; + int c, b, balance, encode; uint8_t *p, *e; size_t size; -#if ARM_COMPLIANT - ptrdiff_t pad; - uint8_t* pos_begin; -#endif - - O = ppheap_buffer(pheap, sizeof(_ppstring), PPSTRING_INIT); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif + + O = ppbytes_buffer(heap, PPSTRING_INIT); for (balance = 0, encode = 0, c = iof_char(I); c >= 0; ) { switch (c) @@ -643,7 +641,7 @@ static ppstring ppscan_crypt_string (iof *I, ppcrypt *crypt, ppheap **pheap) } break; default: - if (ppstring_byte_escape[c] != 0) + if (ppstringesc(c) != 0) encode = 1; iof_put(O, c); c = iof_next(I); @@ -652,63 +650,58 @@ static ppstring ppscan_crypt_string (iof *I, ppcrypt *crypt, ppheap **pheap) /* decrypt the buffer in place, update size */ if (ppstring_decrypt(crypt, O->buf, iof_size(O), O->buf, &size)) O->pos = O->buf + size; + decoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring)); + decoded->data = ppbytes_flush(heap, O, &decoded->size); /* make encoded counterpart */ - if (!encode) + if (encode) { - decoded = ppstring_flush(O, ghost2, size, 0); - ppstring_check_bom(decoded, ghost2); - return decoded; - } - decoded = ppstring_flush_with_ego(O, ghost2, size, PPSTRING_DECODED); - O = ppheap_buffer(pheap, sizeof(_ppstring), ghost2->size); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - for (p = (uint8_t *)decoded, e = (uint8_t *)decoded + ghost2->size; p < e; ++p) - { - switch ((b = ppstring_byte_escape[*p])) + O = ppbytes_buffer(heap, decoded->size + 1); // we don't know + for (p = (uint8_t *)decoded->data, e = p + decoded->size; p < e; ++p) { - case 0: - iof_put(O, *p); - break; - case -1: - iof_put4(O, '\\', (c >> 6) + '0', ((c >> 3) & 7) + '0', (c & 7) + '0'); - break; - default: - iof_put2(O, '\\', b); - break; + b = ppstringesc(*p); + switch (b) + { + case 0: + iof_put(O, *p); + break; + case -1: + iof_put4(O, '\\', ((*p) >> 6) + '0', (((*p) >> 3) & 7) + '0', ((*p) & 7) + '0'); + break; + default: + iof_put2(O, '\\', b); + break; + } } + encoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring)); + encoded->data = ppbytes_flush(heap, O, &encoded->size); + encoded->flags = PPSTRING_ENCODED; + decoded->flags = PPSTRING_DECODED; + encoded->alterego = decoded, decoded->alterego = encoded; + ppstring_check_bom2(decoded, encoded); + } + else + { + decoded->flags = 0; + decoded->alterego = decoded; + ppstring_check_bom(decoded); + encoded = decoded; } - encoded = ppstring_flush_with_ego(O, ghost1, size, PPSTRING_ENCODED); - ppstring_check_bom2(decoded, ghost1, ghost2); - ppstring_set_alter_ego(encoded, ghost1, decoded); - ppstring_set_alter_ego(decoded, ghost2, encoded); return encoded; } - -static ppstring ppscan_crypt_base16 (iof *I, ppcrypt *crypt, ppheap **pheap) +static ppstring * ppscan_crypt_base16 (iof *I, ppcrypt *crypt, ppheap *heap) { - int c, v1, v2; + ppstring *encoded, *decoded; iof *O; - _ppstring *ghost1, *ghost2; - ppstring encoded, decoded; + int c; uint8_t *p, *e; + int8_t h1, h2; size_t size; -#if ARM_COMPLIANT - ptrdiff_t pad; - uint8_t* pos_begin; -#endif - O = ppheap_buffer(pheap, sizeof(_ppstring), PPSTRING_INIT); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - // base16_decode(I, O); // no info about the last char.. - for (c = iof_char(I); c != '>' && c >= 0; ) + + O = ppbytes_buffer(heap, PPSTRING_INIT); + for (c = iof_char(I); c != '>'; ) { - if ((v1 = base16_value(c)) < 0) + if ((h1 = pphex(c)) < 0) { if (ignored_char(c)) { @@ -719,66 +712,51 @@ static ppstring ppscan_crypt_base16 (iof *I, ppcrypt *crypt, ppheap **pheap) } do { c = iof_next(I); - if ((v2 = base16_value(c)) >= 0) + if ((h2 = pphex(c)) >= 0) { c = iof_next(I); break; } if (!ignored_char(c)) // c == '>' || c < 0 or some crap { - v2 = 0; + h2 = 0; break; } } while (1); - iof_put(O, (v1 << 4)|v2); + iof_put(O, (h1 << 4)|h2); } if (c == '>') ++I->pos; /* decrypt the buffer in place, update size */ if (ppstring_decrypt(crypt, O->buf, iof_size(O), O->buf, &size)) O->pos = O->buf + size; - decoded = ppstring_flush_with_ego(O, ghost2, size, PPSTRING_DECODED); - /* recreate an encoded form */ - O = ppheap_buffer(pheap, sizeof(_ppstring), (ghost2->size << 1) + 1); -#if ARM_COMPLIANT - pad=0; - pos_begin = O->pos; -#endif - for (p = (uint8_t *)decoded, e = (uint8_t *)decoded + ghost2->size; p < e; ++p) - iof_set2(O, base16_uc_alphabet[(*p)>>4], base16_uc_alphabet[(*p)&15]); - encoded = ppstring_flush_with_ego(O, ghost1, size, PPSTRING_BASE16|PPSTRING_ENCODED); - ppstring_check_bom2(decoded, ghost1, ghost2); - ppstring_set_alter_ego(encoded, ghost1, decoded); - ppstring_set_alter_ego(decoded, ghost2, encoded); - return encoded; -} + decoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring)); + decoded->data = ppbytes_flush(heap, O, &decoded->size); -/* ppstring alter ego switcher */ + O = ppbytes_buffer(heap, (decoded->size << 1) + 1); + for (p = (uint8_t *)decoded->data, e = p + decoded->size; p < e; ++p) + iof_set2(O, base16_uc_alphabet[(*p) >> 4], base16_uc_alphabet[(*p) & 0xF]); + encoded = (ppstring *)ppstruct_take(heap, sizeof(ppstring)); + encoded->data = ppbytes_flush(heap, O, &encoded->size); -ppstring ppstring_decoded (ppstring string) -{ - const _ppstring *ghost; - ghost = _ppstring_ghost(string); - return (ghost->flags & PPSTRING_ENCODED) ? ppstring_get_alter_ego(string) : string; -} + encoded->flags = PPSTRING_BASE16|PPSTRING_ENCODED; + decoded->flags = PPSTRING_BASE16|PPSTRING_DECODED; + encoded->alterego = decoded, decoded->alterego = encoded; -ppstring ppstring_encoded (ppstring string) -{ - const _ppstring *ghost; - ghost = _ppstring_ghost(string); - return (ghost->flags & PPSTRING_DECODED) ? ppstring_get_alter_ego(string) : string; + ppstring_check_bom2(decoded, encoded); + return encoded; } /* scanner stack */ #define PPSTACK_BUFFER 512 -static void ppstack_init (ppstack *stack, ppheap **pheap) +static void ppstack_init (ppstack *stack, ppheap *heap) { stack->buf = stack->pos = (ppobj *)pp_malloc(PPSTACK_BUFFER * sizeof(ppobj)); stack->size = 0; stack->space = PPSTACK_BUFFER; - stack->pheap = pheap; + stack->heap = heap; } #define ppstack_free_buffer(stack) (pp_free((stack)->buf)) @@ -801,8 +779,8 @@ static void ppstack_resize (ppstack *stack) /* scanner commons */ -#define ppscan_uint(I, u) iof_get_uintlw(I, u) -#define ppread_uint(s, u) string_to_uintlw((const char *)(s), u) +#define ppscan_uint(I, u) iof_get_usize(I, u) +#define ppread_uint(s, u) string_to_usize((const char *)(s), u) static ppobj * ppscan_numobj (iof *I, ppobj *obj, int negative) { @@ -870,7 +848,7 @@ static int ppscan_keyword (iof *I, const char *keyword, size_t size) { size_t i; int c; - if (iof_left(I) >= size) + if ((size_t)iof_left(I) >= size) { if (memcmp(I->pos, keyword, size) != 0) return 0; @@ -879,7 +857,7 @@ static int ppscan_keyword (iof *I, const char *keyword, size_t size) } // sticky case, we can't go back for (i = 0, c = iof_char(I); i < size; ++i, ++keyword, c = iof_next(I)) - if (i != c) + if (c < 0 || *keyword != c) /* PJ20190503 bugfix: there was (i!=c), we actually never get here anyway */ return 0; return 1; } @@ -888,9 +866,9 @@ static int ppscan_keyword (iof *I, const char *keyword, size_t size) /* objects parser */ -static ppref * ppref_unresolved (ppheap **pheap, ppuint refnumber, ppuint refversion) +static ppref * ppref_unresolved (ppheap *heap, ppuint refnumber, ppuint refversion) { - ppref *ref = (ppref *)ppheap_take(pheap, sizeof(ppref)); + ppref *ref = (ppref *)ppstruct_take(heap, sizeof(ppref)); memset(ref, 0, sizeof(ppref)); ref->object.type = PPNONE; ref->number = refnumber; @@ -1007,7 +985,7 @@ static ppobj * ppscan_obj (iof *I, ppdoc *pdf, ppxref *xref) refversion = (obj + 1)->integer; //if (xref != NULL) // loggerf("unresolved reference %s", ppref_str(refnumber, refversion)); - ref = ppref_unresolved(stack->pheap, refnumber, refversion); + ref = ppref_unresolved(stack->heap, refnumber, refversion); } obj->type = PPREF; obj->ref = ref; @@ -1055,14 +1033,15 @@ and scientific numbers notation. It takes ppstack * as context (no ppdoc *) to b to run contents parser beyond the scope of ppdoc heap. */ -static ppstring ppstring_inline (iof *I, ppdict *imagedict, ppheap **pheap); +static ppstring * ppstring_inline (iof *I, ppdict *imagedict, ppheap *heap); static ppobj * ppscan_psobj (iof *I, ppstack *stack) { int c; ppobj *obj, *op; size_t size, mark; - ppname exec; + ppname *exec; + ppbyte *data; c = iof_char(I); switch (c) @@ -1079,7 +1058,7 @@ static ppobj * ppscan_psobj (iof *I, ppstack *stack) return ppscan_numobj_frac(I, ppstack_push(stack), 0); obj = ppstack_push(stack); obj->type = PPNAME; - obj->name = ppscan_exec(I, stack->pheap, '+'); + obj->name = ppscan_exec(I, stack->heap, '+'); return obj; case '-': c = iof_next(I); @@ -1089,19 +1068,19 @@ static ppobj * ppscan_psobj (iof *I, ppstack *stack) return ppscan_numobj_frac(I, ppstack_push(stack), 1); obj = ppstack_push(stack); obj->type = PPNAME; - obj->name = ppscan_exec(I, stack->pheap, '-'); + obj->name = ppscan_exec(I, stack->heap, '-'); return obj; case '/': ++I->pos; obj = ppstack_push(stack); obj->type = PPNAME; - obj->name = ppscan_name(I, stack->pheap); + obj->name = ppscan_name(I, stack->heap); return obj; case '(': ++I->pos; obj = ppstack_push(stack); obj->type = PPSTRING; - obj->string = ppscan_string(I, stack->pheap); + obj->string = ppscan_string(I, stack->heap); return obj; case '[': mark = stack->size; @@ -1122,7 +1101,7 @@ static ppobj * ppscan_psobj (iof *I, ppstack *stack) size = stack->size - mark - 1; obj = ppstack_at(stack, mark); obj->type = PPARRAY; - obj->array = pparray_create(ppstack_at(stack, mark + 1), size, stack->pheap); + obj->array = pparray_create(ppstack_at(stack, mark + 1), size, stack->heap); ppstack_pop(stack, size); return obj; case '<': @@ -1147,51 +1126,49 @@ static ppobj * ppscan_psobj (iof *I, ppstack *stack) size = stack->size - mark - 1; obj = ppstack_at(stack, mark); obj->type = PPDICT; - obj->dict = ppdict_create(ppstack_at(stack, mark + 1), size, stack->pheap); + obj->dict = ppdict_create(ppstack_at(stack, mark + 1), size, stack->heap); ppstack_pop(stack, size); return obj; } obj = ppstack_push(stack); obj->type = PPSTRING; if (c == '~') - ++I->pos, obj->string = ppscan_base85(I, stack->pheap); + ++I->pos, obj->string = ppscan_base85(I, stack->heap); else - obj->string = ppscan_base16(I, stack->pheap); + obj->string = ppscan_base16(I, stack->heap); return obj; default: - if (c < 0 || !ppname_byte_lookup[c]) + if (!ppnamebyte(c)) break; // forbid empty names; dead loop otherwise ++I->pos; /* true false null practically don't occur in streams so it makes sense to assume that we get an operator name here. If it happen to be a keyword we could give back those several bytes to the heap but.. heap buffer is tricky enough. */ - exec = ppscan_exec(I, stack->pheap, c); + exec = ppscan_exec(I, stack->heap, (uint8_t)c); + data = exec->data; obj = ppstack_push(stack); - switch (exec[0]) + switch (data[0]) { case 't': - if (exec[1] == 'r' && exec[2] == 'u' && exec[3] == 'e' && exec[4] == '\0') + if (data[1] == 'r' && data[2] == 'u' && data[3] == 'e' && data[4] == '\0') { obj->type = PPBOOL; obj->integer = 1; - // todo: drop exec return obj; } break; case 'f': - if (exec[1] == 'a' && exec[2] == 'l' && exec[3] == 's' && exec[4] == 'e' && exec[5] == '\0') + if (data[1] == 'a' && data[2] == 'l' && data[3] == 's' && data[4] == 'e' && data[5] == '\0') { obj->type = PPBOOL; obj->integer = 0; - // todo: drop exec return obj; } break; case 'n': - if (exec[1] == 'u' && exec[2] == 'l' && exec[3] == 'l' && exec[4] == '\0') + if (data[1] == 'u' && data[2] == 'l' && data[3] == 'l' && data[4] == '\0') { obj->type = PPNULL; obj->any = NULL; - // todo: drop exec return obj; } break; @@ -1204,9 +1181,10 @@ static ppobj * ppscan_psobj (iof *I, ppstack *stack) We treat the image as a single syntactic token; BI starts collecting a dict, ID is the beginning of the data. Effectively EI operator obtains two operands - dict and string. It is ok to put three items onto the stack, callers dont't assume there is just one. */ - if (exec[1] == 'I' && exec[2] == '\0') + if (data[1] == 'I' && data[2] == '\0') { ppdict *imagedict; + ppname *name; /* key val pairs -> dict */ mark = stack->size - 1; obj->type = PPMARK; @@ -1219,32 +1197,37 @@ static ppobj * ppscan_psobj (iof *I, ppstack *stack) ppstack_pop(stack, size); return NULL; } - if (op->type == PPNAME && ppname_exec(op->name)) + if (op->type == PPNAME) { - if (!ppname_is(op->name, "ID")) - { // weird - size = stack->size - mark; - ppstack_pop(stack, size); - return NULL; + name = op->name; + if (name->flags & PPNAME_EXEC) + { + if (name->size != 2 || name->data[0] != 'I' || name->data[1] != 'D') + { // weird + size = stack->size - mark; + ppstack_pop(stack, size); + return NULL; + } + break; } - break; } } size = stack->size - mark - 1; obj = ppstack_at(stack, mark); obj->type = PPDICT; - obj->dict = imagedict = ppdict_create(ppstack_at(stack, mark + 1), size, stack->pheap); + obj->dict = imagedict = ppdict_create(ppstack_at(stack, mark + 1), size, stack->heap); ppstack_pop(stack, size); /* put image data string */ obj = ppstack_push(stack); obj->type = PPSTRING; - obj->string = ppstring_inline(I, imagedict, stack->pheap);; + obj->string = ppstring_inline(I, imagedict, stack->heap);; /* put EI operator name */ obj = ppstack_push(stack); obj->type = PPNAME; - obj->name = ppexec_internal("EI", 2, stack->pheap); + obj->name = ppexec_internal("EI", 2, stack->heap); return obj; } + break; } obj->type = PPNAME; obj->name = exec; @@ -1256,36 +1239,40 @@ static ppobj * ppscan_psobj (iof *I, ppstack *stack) /* We try to get the exact inline image length from its dict params. If cannot predict the length, we have to scan the input until 'EI'. I've checked on may examples that it gives the same results but one can never be sure, as 'EI' might happen to be a part of the data. -Stripping white char is also very heuristic; \0 is a white char in PDF and very likely to be a data byte.. weak method. +Stripping white char is also very heuristic; \0 is a white char in PDF and very likely to be a data byte.. weak method (pdf spec page 352). + +Revision 20190327: inline images may be compressed, in which case we can't predict the length. */ static size_t inline_image_length (ppdict *dict) { ppuint w, h, bpc, colors; - ppname cs; + ppname *cs; - if (ppdict_get_uint(dict, "W", &w) && ppdict_get_uint(dict, "H", &h) && ppdict_get_uint(dict, "BPC", &bpc) && (cs = ppdict_get_name(dict, "CS")) != NULL) + if (ppdict_get_name(dict, "F") == NULL) { - if (ppname_is(cs, "DeviceGray")) - colors = 1; - else if (ppname_is(cs, "DeviceRGB")) - colors = 3; - else if (ppname_is(cs, "DeviceCMYK")) - colors = 4; - else - return PP_LENGTH_UNKNOWN; - return (w * h * bpc * colors + 7) >> 3; + if (ppdict_get_uint(dict, "W", &w) && ppdict_get_uint(dict, "H", &h) && ppdict_get_uint(dict, "BPC", &bpc) && (cs = ppdict_get_name(dict, "CS")) != NULL) + { + if (ppname_is(cs, "DeviceGray")) + colors = 1; + else if (ppname_is(cs, "DeviceRGB")) + colors = 3; + else if (ppname_is(cs, "DeviceCMYK")) + colors = 4; + else + return PP_LENGTH_UNKNOWN; + return (w * h * bpc * colors + 7) >> 3; + } } return PP_LENGTH_UNKNOWN; } -static ppstring ppstring_inline (iof *I, ppdict *imagedict, ppheap **pheap) +static ppstring * ppstring_inline (iof *I, ppdict *imagedict, ppheap *heap) { iof *O; int c, d, e; size_t length, leftin, leftout, bytes; - O = ppheap_buffer(pheap, sizeof(_ppstring), PPSTRING_INIT); c = iof_char(I); if (ignored_char(c)) c = iof_next(I); @@ -1293,6 +1280,7 @@ static ppstring ppstring_inline (iof *I, ppdict *imagedict, ppheap **pheap) length = inline_image_length(imagedict); if (length != PP_LENGTH_UNKNOWN) { + O = ppbytes_buffer(heap, length); while (length > 0 && iof_readable(I) && iof_writable(O)) { leftin = iof_left(I); @@ -1312,6 +1300,7 @@ static ppstring ppstring_inline (iof *I, ppdict *imagedict, ppheap **pheap) } else { + O = ppbytes_buffer(heap, PPSTRING_INIT); // ? while (c >= 0) { if (c == 'E') @@ -1320,7 +1309,7 @@ static ppstring ppstring_inline (iof *I, ppdict *imagedict, ppheap **pheap) if (d == 'I') { e = iof_next(I); - if (!ppname_byte_lookup[e]) + if (!ppnamebyte(e)) { /* strip one newline from the end and stop */ if (O->pos - 2 >= O->buf) // sanity { @@ -1351,7 +1340,7 @@ static ppstring ppstring_inline (iof *I, ppdict *imagedict, ppheap **pheap) } } } - return ppstring_buffer(O, pheap); + return ppstring_buffer(O, heap); } /* input reader */ @@ -1378,18 +1367,18 @@ static void ppdoc_reader_init (ppdoc *pdf, iof_file *input) if (input->flags & IOF_DATA) { pdf->buffer = NULL; // input iof_file is the buffer - iof_string_reader(I, NULL, 0); // gets IOF_DATA flag + iof_string_reader(I, NULL, 0); } else { - pdf->buffer = (uint8_t *)ppheap_take(&pdf->heap, PPDOC_BUFFER); + pdf->buffer = (uint8_t *)ppbytes_take(&pdf->heap, PPDOC_BUFFER); iof_setup_file_handle_reader(I, NULL, 0, iof_file_get_fh(input)); // gets IOF_FILE_HANDLE flag and FILE * I->space = PPDOC_BUFFER; // used on refill } } /* -Whenever we need to read the input file, we fseek the to the given offset and fread to to the private buffer. +Whenever we need to read the input file, we fseek the to the given offset and fread to the private buffer. The length we need is not always predictable, in which case PPDOC_BUFFER bytes are read (keep it small). I->buf = I->pos is set to the beginning, I->end set to the end (end is the first byte one shouldn't read). */ @@ -1400,7 +1389,7 @@ static iof * ppdoc_reader (ppdoc *pdf, size_t offset, size_t length) iof *I; input = &pdf->input; I = &pdf->reader; - if (iof_file_seek(input, offset, SEEK_SET) != 0) + if (iof_file_seek(input, (long)offset, SEEK_SET) != 0) return NULL; I->flags &= ~IOF_STOPPED; if (input->flags & IOF_DATA) @@ -1450,7 +1439,7 @@ static int ppdoc_tail (ppdoc *pdf, iof_file *input, size_t *pxrefoffset) if (iof_file_seek(input, 0, SEEK_END) != 0) return 0; pdf->filesize = (size_t)iof_file_tell(input); - // simple heuristic to avoif fgetc() / fseek(-2) hiccup: keep seeking back by len(startxref) + 1 == 10 + // simple heuristic to avoid fgetc() / fseek(-2) hiccup: keep seeking back by len(startxref) + 1 == 10 // until a letter found (assuming liberal white characters and tail length) for (back = 1, tailbytes = 0; ; ++back) { @@ -1484,7 +1473,7 @@ static int ppdoc_tail (ppdoc *pdf, iof_file *input, size_t *pxrefoffset) return 0; } } - return 0; + return 0; // never reached } /* xref/body */ @@ -1501,7 +1490,7 @@ static int ppscan_start_entry (iof *I, ppref *ref) static int ppscan_skip_entry (iof *I) { - size_t u; + ppuint u; ppscan_find(I); if (!ppscan_uint(I, &u)) return 0; ppscan_find(I); if (!ppscan_uint(I, &u)) return 0; ppscan_find(I); if (!ppscan_key(I, "obj")) return 0; @@ -1568,7 +1557,7 @@ First created xref becomes a pdf->xref (top xref). We link that early to control */ // Every xref table item "0000000000 00000 n" is said to be terminated with 2-byte EOL but we don't like relying on whites. -#define xref_item_length (10+1+5+1+1) +#define xref_item_length (10 + 1 + 5 + 1 + 1) static ppxref * ppxref_load_table (iof *I, ppdoc *pdf, size_t xrefoffset) { @@ -1583,6 +1572,7 @@ static ppxref * ppxref_load_table (iof *I, ppdoc *pdf, size_t xrefoffset) buffer[xref_item_length] = '\0'; xref = ppxref_create(pdf, 0, xrefoffset); if (pdf->xref == NULL) pdf->xref = xref; + for (ppscan_find(I); ppscan_uint(I, &first); ppscan_find(I)) { ppscan_find(I); @@ -1592,7 +1582,7 @@ static ppxref * ppxref_load_table (iof *I, ppdoc *pdf, size_t xrefoffset) continue; xref->count += count; xrefsection = NULL; - ref = (ppref *)ppheap_take(&pdf->heap, count * sizeof(ppref)); + ref = (ppref *)ppstruct_take(&pdf->heap, count * sizeof(ppref)); for (refindex = 0; refindex < count; ++refindex, ++ref) { ref->xref = xref; @@ -1626,8 +1616,7 @@ static ppxref * ppxref_load_table (iof *I, ppdoc *pdf, size_t xrefoffset) } } /* sort section */ - if (!ppxref_sort(xref)) - ; // case of xref->size == 0 handled by ppxref_load_chain() + ppxref_sort(xref); // case of xref->size == 0 handled by ppxref_load_chain() /* get trailer ignoring refs */ if (!ppscan_key(I, "trailer")) return NULL; @@ -1720,13 +1709,14 @@ static ppxref * ppxref_load_stream (iof *I, ppdoc *pdf, size_t xrefoffset) for (sectionindex = 0; sectionindex < sections; ++sectionindex, sectionfirst += 2) { sectioncount = sectionfirst + 1; + first = 0, count = 0; // warnings if (!ppobj_get_uint(sectionfirst, first) || !ppobj_get_uint(sectioncount, count)) goto xref_stream_error; if (count == 0) continue; xref->count += count; xrefsection = NULL; - ref = (ppref *)ppheap_take(&pdf->heap, count * sizeof(ppref)); + ref = (ppref *)ppstruct_take(&pdf->heap, count * sizeof(ppref)); for (refindex = 0; refindex < count; ++refindex, ++ref) { ref->xref = xref; @@ -1781,8 +1771,7 @@ static ppxref * ppxref_load_stream (iof *I, ppdoc *pdf, size_t xrefoffset) } } /* sort sections */ - if (!ppxref_sort(xref)) - ; // case of xref->size == 0 handled by ppxref_load_chain() + ppxref_sort(xref); // case of xref->size == 0 handled by ppxref_load_chain() /* close the stream _before_ loading prev xref */ ppstream_done(xrefstream); /* load prev and return */ @@ -1808,7 +1797,7 @@ static ppxref * ppxref_load_chain (ppdoc *pdf, ppxref *xref) trailer = ppxref_trailer(xref); if (!ppdict_get_uint(trailer, "Prev", &xrefoffset)) // XRefStm is useless - return xref; // missing /Prev is obviously ok + return xref; for (nextxref = pdf->xref; nextxref != NULL; nextxref = nextxref->prev) if (nextxref->offset == xrefoffset) // insane return NULL; @@ -1827,6 +1816,7 @@ static ppxref * ppxref_load_chain (ppdoc *pdf, ppxref *xref) static ppxref * ppxref_load (ppdoc *pdf, size_t xrefoffset) { iof *I; + if ((I = ppdoc_reader(pdf, xrefoffset, PP_LENGTH_UNKNOWN)) == NULL) return NULL; ppscan_find(I); @@ -1865,7 +1855,7 @@ static void fix_trailer_references (ppdoc *pdf) { ppxref *xref; ppdict *trailer; - ppname *pkey; + ppname **pkey; ppobj *obj; ppref *ref; for (xref = pdf->xref; xref != NULL; xref = xref->prev) @@ -1925,7 +1915,7 @@ static void ppdoc_load_entries (ppdoc *pdf) ppxref *xref; ppxsec *xsec; ppobj *obj; - ppname type; + ppname *type; ppcrypt *crypt; ppstream *stream; @@ -1947,7 +1937,7 @@ static void ppdoc_load_entries (ppdoc *pdf) ++pref; ++offindex; if (ref->object.type != PPNONE) // might be preloaded already (/Encrypt dict, stream filter dicts, stream /Length..) - continue; + continue; if (offindex < objects) ref->length = (*pref)->offset - ref->offset; else @@ -2014,7 +2004,7 @@ static void ppdoc_load_entries (ppdoc *pdf) ppstream_info(stream, pdf); } if (!ppdoc_load_objstm(stream, pdf, ref->xref)) - loggerf("invalid objects stream %s at offset " PPSIZEF, ppref_str(ref->number, ref->version), ref->offset); + loggerf("invalid objects stream %s at offset " PPSIZEF, ppref_str(ref->number, ref->version), ref->offset); } } @@ -2231,22 +2221,36 @@ static ppdoc * ppdoc_read (ppdoc *pdf, iof_file *input) static void ppdoc_pages_init (ppdoc *pdf); +/* +20191214: We used to allocate ppdoc, as all other structs, from the internal heap: + + ppheap heap; + ppheap_init(&heap); + pdf = (ppdoc *)ppstruct_take(&heap, sizeof(ppdoc)); + pdf->heap = heap; + ppbytes_buffer_init(&pdf->heap); + ... + +So ppdoc pdf was allocated from the heap owned by the pdf itself. Somewhat tricky, but should work fine, +as from that point nothing refered to a local heap variable addres. For some reason that causes a crash +on openbsd. +*/ + static ppdoc * ppdoc_create (iof_file *input) { ppdoc *pdf; - ppheap *heap; - heap = ppheap_new(); - pdf = (ppdoc *)ppheap_take(&heap, sizeof(ppdoc)); - pdf->flags = 0; - pdf->heap = heap; - pdf->xref = NULL; - pdf->version[0] = '\0'; - pdf->crypt = NULL; - pdf->cryptstatus = PPCRYPT_PASS; // force encryption check on ppdoc_read() -> ppdoc_crypt_pass() + pdf = (ppdoc *)pp_malloc(sizeof(ppdoc)); + ppheap_init(&pdf->heap); + ppbytes_buffer_init(&pdf->heap); ppstack_init(&pdf->stack, &pdf->heap); ppdoc_reader_init(pdf, input); ppdoc_pages_init(pdf); + pdf->xref = NULL; + pdf->crypt = NULL; + pdf->cryptstatus = PPCRYPT_PASS; // check on ppdoc_read() -> ppdoc_crypt_pass() + pdf->flags = 0; + pdf->version[0] = '\0'; if (ppdoc_read(pdf, &pdf->input) != NULL) return pdf; ppdoc_free(pdf); @@ -2264,20 +2268,31 @@ ppdoc * ppdoc_load (const char *filename) return ppdoc_create(&input); } +ppdoc * ppdoc_filehandle (FILE *file, int closefile) +{ + iof_file input; + if (file == NULL) + return NULL; + iof_file_init(&input, file); + if (closefile) + input.flags |= IOF_CLOSE_FILE; + return ppdoc_create(&input); +} + ppdoc * ppdoc_mem (const void *data, size_t size) { - iof_file input; - iof_file_rdata_init(&input, data, size); - input.flags |= IOF_BUFFER_ALLOC; // todo: 3 modes: borrow, take over, copy? - return ppdoc_create(&input); + iof_file input; + iof_file_rdata_init(&input, data, size); + input.flags |= IOF_BUFFER_ALLOC; + return ppdoc_create(&input); } void ppdoc_free (ppdoc *pdf) { - //iof_file_free(&pdf->input); iof_file_decref(&pdf->input); ppstack_free_buffer(&pdf->stack); - ppheap_free(pdf->heap); // last! + ppheap_free(&pdf->heap); + pp_free(pdf); } ppcrypt_status ppdoc_crypt_status (ppdoc *pdf) @@ -2292,16 +2307,16 @@ ppint ppdoc_permissions (ppdoc *pdf) /* pages access */ -static pparray * pppage_node (ppdict *dict, ppuint *count, ppname *type) +static pparray * pppage_node (ppdict *dict, ppuint *count, ppname **type) { - ppname *pkey, key; + ppname **pkey, *key; ppobj *obj; pparray *kids = NULL; *count = 0; *type = NULL; for (ppdict_first(dict, pkey, obj); (key = *pkey) != NULL; ppdict_next(pkey, obj)) { - switch (key[0]) + switch (key->data[0]) { case 'T': if (ppname_is(key, "Type")) @@ -2325,7 +2340,7 @@ static pparray * pppage_node (ppdict *dict, ppuint *count, ppname *type) ppuint ppdoc_page_count (ppdoc *pdf) { ppref *ref; - ppname type; + ppname *type; ppuint count; if ((ref = ppxref_pages(pdf->xref)) == NULL) return 0; @@ -2342,8 +2357,7 @@ ppref * ppdoc_page (ppdoc *pdf, ppuint index) size_t size, i; ppobj *r, *o; ppref *ref; - ppname type; - + ppname *type; if ((ref = ppxref_pages(pdf->xref)) == NULL) return NULL; @@ -2420,7 +2434,7 @@ static void ppdoc_pages_init (ppdoc *pdf) { pppages *pages; pages = &pdf->pages; - pages->root = pages->parent = pages->buffer; + pages->root = pages->parent = &pages->buffer[0]; pages->depth = 0; pages->space = PPPAGES_STACK_DEPTH; } @@ -2433,7 +2447,7 @@ static ppkids * pppages_push (ppdoc *pdf, pparray *kids) if (pages->depth == pages->space) { pages->space <<= 1; - newroot = (ppkids *)ppheap_take(&pdf->heap, pages->space * sizeof(ppkids)); + newroot = (ppkids *)ppstruct_take(&pdf->heap, pages->space * sizeof(ppkids)); memcpy(newroot, pages->root, pages->depth * sizeof(ppkids)); pages->root = newroot; } @@ -2450,12 +2464,15 @@ static ppref * ppdoc_pages_group_first (ppdoc *pdf, ppref *ref) ppdict *dict; pparray *kids; ppuint count; - ppname type; + ppname *type; + ppobj *o; dict = ref->object.dict; // typecheck made by callers while ((kids = pppage_node(dict, &count, &type)) != NULL) { - if ((ref = pparray_get_ref(kids, 0)) == NULL || ref->object.type != PPDICT) + if ((o = pparray_get_obj(kids, 0)) == NULL) // empty /Kids + return ppdoc_next_page(pdf); + if ((ref = ppobj_get_ref(o)) == NULL || ref->object.type != PPDICT) return NULL; pppages_push(pdf, kids); dict = ref->object.dict; @@ -2507,25 +2524,24 @@ ppref * ppdoc_next_page (ppdoc *pdf) ppcontext * ppcontext_new (void) { - ppheap *heap; ppcontext *context; - heap = ppheap_new(); - context = (ppcontext *)pp_malloc(sizeof(ppcontext)); // not from priv heap, as we delete it on renew - context->heap = heap; + context = (ppcontext *)pp_malloc(sizeof(ppcontext)); + ppheap_init(&context->heap); + ppbytes_buffer_init(&context->heap); ppstack_init(&context->stack, &context->heap); return context; } void ppcontext_done (ppcontext *context) { - ppheap_renew(context->heap); + ppheap_renew(&context->heap); ppstack_clear(&context->stack); } void ppcontext_free (ppcontext *context) { ppstack_free_buffer(&context->stack); - ppheap_free(context->heap); + ppheap_free(&context->heap); pp_free(context); } @@ -2590,7 +2606,7 @@ ppstream * ppcontents_next (ppdict *dict, ppstream *stream) return NULL; } -static ppobj * ppcontents_op (iof *I, ppstack *stack, size_t *psize, ppname *pname) +static ppobj * ppcontents_op (iof *I, ppstack *stack, size_t *psize, ppname **pname) { ppobj *obj; ppstack_clear(stack); @@ -2605,7 +2621,7 @@ static ppobj * ppcontents_op (iof *I, ppstack *stack, size_t *psize, ppname *pna return stack->buf; } -ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname) +ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname **pname) { iof *I; if ((I = ppstream_read(stream, 1, 0)) == NULL) @@ -2613,7 +2629,7 @@ ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize return ppcontents_op(I, &context->stack, psize, pname); } -ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname *pname) +ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname **pname) { return ppcontents_op(ppstream_iof(stream), &context->stack, psize, pname); } @@ -2702,12 +2718,12 @@ ppmatrix * ppdict_get_matrix (ppdict *dict, const char *name, ppmatrix *matrix) void pplog_callback (pplogger_callback logger, void *alien) { - logger_callback((logger_function)logger, alien); + logger_callback((logger_function)logger, alien); } int pplog_prefix (const char *prefix) { - return logger_prefix(prefix); + return logger_prefix(prefix); } /* version */ @@ -2741,13 +2757,13 @@ ppuint ppdoc_objects (ppdoc *pdf) size_t ppdoc_memory (ppdoc *pdf, size_t *waste) { + mem_info info; size_t used; - ppheap *heap; - used = 0, *waste = 0; - for (heap = pdf->heap; heap != NULL; heap = heap->prev) - { - used += heap->space; - *waste += heap->size; - } + ppbytes_heap_info(&pdf->heap, &info, 0); + ppstruct_heap_info(&pdf->heap, &info, 1); + + *waste = info.ghosts + info.blockghosts + info.left; // info.ghosts == 0 + used = info.used + *waste; + used += pdf->stack.space * sizeof(ppobj); return used; } diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppload.h b/Build/source/texk/web2c/luatexdir/luapplib/src/ppload.h index 16392839893..f9ecca3b9a0 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppload.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppload.h @@ -7,7 +7,7 @@ typedef struct { ppobj *pos; // current ppobj * size_t size; // stack size size_t space; // available space - ppheap **pheap; // allocator (parent pdf->stack->pheap or own) + ppheap *heap; // allocator (parent pdf->stack->heap or parent context) } ppstack; typedef struct { @@ -26,28 +26,32 @@ typedef struct { } pppages; struct ppdoc { - char version[5]; + /* input */ iof_file input; iof reader; uint8_t *buffer; size_t filesize; - ppxref *xref; - ppheap *heap; + /* heap */ + ppheap heap; ppstack stack; + /* output struct */ + ppxref *xref; pppages pages; - int flags; ppcrypt *crypt; ppcrypt_status cryptstatus; + int flags; + char version[5]; }; #define PPDOC_LINEARIZED (1 << 0) ppobj * ppdoc_load_entry (ppdoc *pdf, ppref *ref); #define ppobj_preloaded(pdf, obj) ((obj)->type != PPREF ? (obj) : ((obj)->ref->object.type == PPNONE ? ppdoc_load_entry(pdf, (obj)->ref) : &(obj)->ref->object)) -ppstring ppstring_internal (const void *data, size_t size, ppheap **pheap); + +ppstring * ppstring_internal (const void *data, size_t size, ppheap *heap); struct ppcontext { - ppheap *heap; + ppheap heap; ppstack stack; }; diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppstream.c b/Build/source/texk/web2c/luatexdir/luapplib/src/ppstream.c index 8aa94cb0a09..c88d7e7fc33 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppstream.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppstream.c @@ -4,22 +4,22 @@ ppstream * ppstream_create (ppdoc *pdf, ppdict *dict, size_t offset) { - ppstream *stream; - stream = (ppstream *)ppheap_take(&pdf->heap, sizeof(ppstream)); - stream->dict = dict; - stream->offset = offset; - //if (!ppdict_rget_uint(dict, "Length", &stream->length)) // may be indirect pointing PPNONE at this moment - // stream->length = 0; - stream->length = 0; - stream->filespec = NULL; - stream->filter.filters = NULL; - stream->filter.params = NULL; - stream->filter.count = 0; - stream->input = &pdf->input; - stream->I = NULL; - stream->cryptkey = NULL; - stream->flags = 0; - return stream; + ppstream *stream; + stream = (ppstream *)ppstruct_take(&pdf->heap, sizeof(ppstream)); + stream->dict = dict; + stream->offset = offset; + //if (!ppdict_rget_uint(dict, "Length", &stream->length)) // may be indirect pointing PPNONE at this moment + // stream->length = 0; + stream->length = 0; + stream->filespec = NULL; + stream->filter.filters = NULL; + stream->filter.params = NULL; + stream->filter.count = 0; + stream->input = &pdf->input; + stream->I = NULL; + stream->cryptkey = NULL; + stream->flags = 0; + return stream; } static iof * ppstream_predictor (ppdict *params, iof *N) @@ -42,7 +42,7 @@ static iof * ppstream_decoder (ppstream *stream, ppstreamtp filtertype, ppdict * int flags; iof *F, *P; ppint earlychange; - ppstring cryptkey; + ppstring *cryptkey; switch (filtertype) { @@ -85,9 +85,9 @@ static iof * ppstream_decoder (ppstream *stream, ppstreamtp filtertype, ppdict * if ((cryptkey = stream->cryptkey) == NULL) return N; // /Identity crypt if (stream->flags & PPSTREAM_ENCRYPTED_AES) - return iof_filter_aes_decoder(N, cryptkey, ppstring_size(cryptkey)); + return iof_filter_aes_decoder(N, cryptkey->data, cryptkey->size); if (stream->flags & PPSTREAM_ENCRYPTED_RC4) - return iof_filter_rc4_decoder(N, cryptkey, ppstring_size(cryptkey)); + return iof_filter_rc4_decoder(N, cryptkey->data, cryptkey->size); return NULL; // if neither AES or RC4 but cryptkey present, something went wrong; see ppstream_info() case PPSTREAM_CCITT: case PPSTREAM_DCT: @@ -101,7 +101,7 @@ static iof * ppstream_decoder (ppstream *stream, ppstreamtp filtertype, ppdict * #define ppstream_source(stream) iof_filter_stream_coreader((iof_file *)((stream)->input), (size_t)((stream)->offset), (size_t)((stream)->length)) #define ppstream_auxsource(filename) iof_filter_file_reader(filename) -static ppname ppstream_get_filter_name (ppobj *filterobj, size_t index) +static ppname * ppstream_get_filter_name (ppobj *filterobj, size_t index) { if (filterobj->type == PPNAME) return index == 0 ? filterobj->name : NULL; @@ -249,7 +249,7 @@ void ppstream_done (ppstream *stream) } /* fetching stream info -PJ20190916: revealed it makes sense to do a lilbit more just after parsing stream entry to simplify stream operations +PJ20180916: revealed it makes sense to do a lilbit more just after parsing stream entry to simplify stream operations and extend ppstream api */ @@ -268,9 +268,9 @@ const char * ppstream_filter_name[] = { "Crypt" }; -int ppstream_filter_type (ppname name, ppstreamtp *filtertype) +int ppstream_filter_type (ppname *name, ppstreamtp *filtertype) { - switch (name[0]) + switch (name->data[0]) { case 'A': if (ppname_is(name, "ASCIIHexDecode")) { *filtertype = PPSTREAM_BASE16; return 1; } @@ -304,7 +304,7 @@ void ppstream_info (ppstream *stream, ppdoc *pdf) { // called in ppdoc_load_entries() for every stream, but after loading non-stream objects (eg. /Length..) ppdict *dict, *fparams; ppobj *fobj, *pobj; - ppname fname, tname, owncryptfilter = NULL; + ppname *fname, *tname, *owncryptfilter = NULL; ppcrypt *crypt; ppref *ref; size_t i; @@ -342,9 +342,11 @@ void ppstream_info (ppstream *stream, ppdoc *pdf) } if (farraysize > 0) { - filtertypes = ppheap_take(&pdf->heap, farraysize * sizeof(ppstreamtp)); + filtertypes = (ppstreamtp *)ppstruct_take(&pdf->heap, farraysize * sizeof(ppstreamtp)); if ((pobj = ppdict_rget_obj(dict, paramskey)) != NULL) - filterparams = ppheap_take(&pdf->heap, farraysize * sizeof(ppdict *)); + { + filterparams = (ppdict **)ppstruct_take(&pdf->heap, farraysize * sizeof(ppdict *)); + } for (i = 0; i < farraysize; ++i) { if ((fname = ppstream_get_filter_name(fobj, i)) != NULL && ppstream_filter_type(fname, &filtertype)) @@ -480,10 +482,10 @@ void ppstream_filter_info (ppstream *stream, ppstream_filter *info, int decode) void ppstream_init_buffers (void) { - iof_filters_init(); + iof_filters_init(); } void ppstream_free_buffers (void) { - iof_filters_free(); + iof_filters_free(); } diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppstream.h b/Build/source/texk/web2c/luatexdir/luapplib/src/ppstream.h index 37e34c56ade..37e34c56ade 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppstream.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppstream.h diff --git a/Build/source/texk/web2c/luatexdir/luapplib/pptest1.c b/Build/source/texk/web2c/luatexdir/luapplib/src/pptest1.c index 4671849f551..eabb0eae9cc 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/pptest1.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/pptest1.c @@ -1,6 +1,7 @@ #include <stdio.h> #include "ppapi.h" +#include "util/utiliof.h" static const char * sizenum (size_t s) { @@ -16,38 +17,38 @@ static const char * sizenum (size_t s) static const char * crypt_info (ppdoc *pdf) { - switch (ppdoc_crypt_status(pdf)) - { - case PPCRYPT_NONE: - return "none"; - case PPCRYPT_DONE: - return "empty password"; - case PPCRYPT_PASS: - return "nonempty password"; - default: - break; - } - return "this shouldn't happen"; + switch (ppdoc_crypt_status(pdf)) + { + case PPCRYPT_NONE: + return "none"; + case PPCRYPT_DONE: + return "empty password"; + case PPCRYPT_PASS: + return "nonempty password"; + default: + break; + } + return "this shouldn't happen"; } static void print_info (ppdoc *pdf) { ppdict *info; - ppstring creator, producer; + ppstring *creator, *producer; size_t memused, memwaste; if ((info = ppdoc_info(pdf)) != NULL) { if ((creator = ppdict_rget_string(info, "Creator")) != NULL) - printf(" creator: %s\n", ppstring_decoded(creator)); + printf(" creator: %s\n", ppstring_decoded_data(creator)); if ((producer = ppdict_rget_string(info, "Producer")) != NULL) - printf(" producer: %s\n", ppstring_decoded(producer)); + printf(" producer: %s\n", ppstring_decoded_data(producer)); } printf(" version: %s\n", ppdoc_version_string(pdf)); printf(" protection: %s\n", crypt_info(pdf)); printf(" filesize: %s\n", sizenum(ppdoc_file_size(pdf))); - printf(" objects: " PPUINTF "\n", ppdoc_objects(pdf)); - printf(" pagecount: " PPUINTF "\n", ppdoc_page_count(pdf)); + printf(" objects: %lu\n", (unsigned long)ppdoc_objects(pdf)); + printf(" pagecount: %lu\n", (unsigned long)ppdoc_page_count(pdf)); memused = ppdoc_memory(pdf, &memwaste); printf(" memused: %s\n", sizenum(memused)); printf(" memwaste: %s\n", sizenum(memwaste)); @@ -55,9 +56,9 @@ static void print_info (ppdoc *pdf) static int usage (const char *argv0) { - printf("pplib " pplib_version ", " pplib_author "\n"); - printf("usage: %s file1.pdf file2.pdf ...\n", argv0); - return 0; + printf("pplib " pplib_version ", " pplib_author "\n"); + printf("usage: %s file1.pdf file2.pdf ...\n", argv0); + return 0; } int main (int argc, const char **argv) @@ -65,6 +66,8 @@ int main (int argc, const char **argv) const char *filepath; int a; ppdoc *pdf; + const void *data; + size_t size; if (argc < 2) return usage(argv[0]); @@ -81,6 +84,21 @@ int main (int argc, const char **argv) printf("done.\n"); print_info(pdf); ppdoc_free(pdf); + /* now loading from memory buffer */ + printf("loading %s from mem buffer... ", filepath); + data = iof_copy_file_data(filepath, &size); + if (data != NULL) + { + pdf = ppdoc_mem(data, size); + if (pdf == NULL) + { + printf("failed\n"); + continue; + } + printf("done.\n"); + //print_info(pdf); + ppdoc_free(pdf); + } } return 0; } diff --git a/Build/source/texk/web2c/luatexdir/luapplib/pptest2.c b/Build/source/texk/web2c/luatexdir/luapplib/src/pptest2.c index 4b7f66a0112..766110da4cd 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/pptest2.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/pptest2.c @@ -3,6 +3,7 @@ #include <assert.h> #include "ppapi.h" +/* static const char * get_file_name (const char *path) { const char *fn, *p; @@ -11,6 +12,7 @@ static const char * get_file_name (const char *path) fn = p + 1; return fn; } +*/ static void box_info (ppdict *pagedict, FILE *fh) { @@ -24,21 +26,19 @@ static void box_info (ppdict *pagedict, FILE *fh) static int usage (const char *argv0) { - printf("pplib " pplib_version ", " pplib_author "\n"); - printf("usage: %s file1.pdf file2.pdf ...\n", argv0); - return 0; + printf("pplib " pplib_version ", " pplib_author "\n"); + printf("usage: %s file1.pdf file2.pdf ...\n", argv0); + return 0; } -#define OUTDIR "." - static void log_callback (const char *message, void *alien) { - fprintf((FILE *)alien, "\nooops: %s\n", message); + fprintf((FILE *)alien, "\nooops: %s\n", message); } int main (int argc, const char **argv) { - const char *filepath, *filename; + const char *filepath; int a; ppdoc *pdf; ppref *pageref; @@ -51,7 +51,7 @@ int main (int argc, const char **argv) size_t size; ppcontext *context; ppobj *obj; - ppname op; + ppname *op; size_t operators; if (argc < 2) @@ -72,22 +72,21 @@ int main (int argc, const char **argv) printf("done.\n"); switch (ppdoc_crypt_status(pdf)) { - case PPCRYPT_NONE: - case PPCRYPT_DONE: - break; - case PPCRYPT_PASS: - if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE || ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE) - break; + case PPCRYPT_NONE: + case PPCRYPT_DONE: + break; + case PPCRYPT_PASS: + if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE || ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE) + break; printf("sorry, password needed\n"); ppdoc_free(pdf); continue; - case PPCRYPT_FAIL: - printf("sorry, encryption failed\n"); - ppdoc_free(pdf); - continue; + case PPCRYPT_FAIL: + printf("sorry, encryption failed\n"); + ppdoc_free(pdf); + continue; } - filename = get_file_name(filepath); - sprintf(outname, OUTDIR "/%s.out", filename); + sprintf(outname, "%s.out", filepath); fh = fopen(outname, "wb"); if (fh == NULL) { @@ -122,10 +121,10 @@ int main (int argc, const char **argv) obj != NULL; obj = ppcontents_next_op(context, stream, &size, &op)) ++operators; - fprintf(fh, "%%%% OPERATORS count " PPSIZEF "\n", operators); + fprintf(fh, "%%%% OPERATORS count %lu\n", (unsigned long)operators); ppstream_done(stream); //obj = ppcontents_parse(context, stream, &size); - //fprintf(fh, "%%%% items count " PPSIZEF "\n", size); + //fprintf(fh, "%%%% items count %lu\n", (unsigned long)size); fprintf(fh, "\n"); } ppcontext_done(context); @@ -134,6 +133,6 @@ int main (int argc, const char **argv) ppdoc_free(pdf); } ppcontext_free(context); - ppstream_free_buffers(); + ppstream_free_buffers(); return 0; } diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/pptest3.c b/Build/source/texk/web2c/luatexdir/luapplib/src/pptest3.c new file mode 100644 index 00000000000..815ed51b6b6 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/pptest3.c @@ -0,0 +1,123 @@ + +#include <stdio.h> +//#include "ppapi.h" +#include "pplib.h" +#include "assert.h" + +static int usage (const char *argv0) +{ + printf("pplib " pplib_version ", " pplib_author "\n"); + printf("usage: %s file1.pdf file2.pdf ...\n", argv0); + return 0; +} + +static void print_result_filter (ppstream *stream, int decode) +{ + ppstream_filter info; + size_t i; + + ppstream_filter_info(stream, &info, decode); + printf(" when %s: /Filter [", decode ? "uncompressed" : "compressed"); + for (i = 0; i < info.count; ++i) + printf(" /%s", ppstream_filter_name[info.filters[i]]); + printf(" ]"); + if (info.params != NULL) + { + printf(" /DecodeParms ["); + for (i = 0; i < info.count; ++i) + printf(" %s", info.params[i] != NULL ? "<<...>>" : "null"); + printf(" ]"); + } + printf("\n"); +} + +static void print_stream_info (ppref *ref, ppstream *stream) +{ + size_t length; + printf("object %lu %lu R\n", (unsigned long)ref->number, (unsigned long)ref->version); + if (stream->flags & PPSTREAM_FILTER) + printf(" filtered "); + else + printf(" plain "); + if (stream->flags & PPSTREAM_IMAGE) + printf("image "); + else + printf("stream "); + if (stream->flags & PPSTREAM_ENCRYPTED) + printf("encrypted "); + if (stream->flags & PPSTREAM_NOT_SUPPORTED) + printf("invalid "); + if (!ppdict_rget_uint(stream->dict, "Length", &length)) + length = 0; + assert(stream->length == length); + printf("length %lu (/Length %lu)\n", (unsigned long)stream->length, (unsigned long)length); + print_result_filter(stream, 0); + print_result_filter(stream, 1); +} + +static void check_stream_chunks (ppstream *stream) +{ + size_t sum, size; + uint8_t *data; + const int decode[2] = {0, 1}; + int d; + + for (d = 0; d < 2; ++d) + { + for (sum = 0, data = ppstream_first(stream, &size, decode[d]); data != NULL; data = ppstream_next(stream, &size)) + sum += size; + ppstream_done(stream); + ppstream_all(stream, &size, decode[d]); + ppstream_done(stream); + assert(sum == size); + printf(" %s chunks size [%lu]\n", (decode[d] ? "decoded" : "raw"), (unsigned long)size); + } +} + +#define USE_BUFFERS_POOL 1 + +int main (int argc, const char **argv) +{ + const char *filepath; + int a; + ppdoc *pdf; + ppxref *xref; + ppxsec *xsec; + size_t xi; + ppuint refnum; + ppref *ref; + + if (argc < 2) + return usage(argv[0]); + if (USE_BUFFERS_POOL) + ppstream_init_buffers(); + for (a = 1; a < argc; ++a) + { + filepath = argv[a]; + printf("loading %s... ", filepath); + pdf = ppdoc_load(filepath); + if (pdf == NULL) + { + printf("failed\n"); + continue; + } + printf("done.\n"); + for (xref = ppdoc_xref(pdf); xref != NULL; xref = ppxref_prev(xref)) + { + for (xi = 0, xsec = xref->sects; xi < xref->size; ++xi, ++xsec) + { + for (refnum = xsec->first, ref = xsec->refs; refnum <= xsec->last; ++refnum, ++ref) + { + if (ref->object.type != PPSTREAM) + continue; + print_stream_info(ref, ref->object.stream); + check_stream_chunks(ref->object.stream); + } + } + } + ppdoc_free(pdf); + } + if (USE_BUFFERS_POOL) + ppstream_free_buffers(); + return 0; +} diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppxref.c b/Build/source/texk/web2c/luatexdir/luapplib/src/ppxref.c index 648d7f1d32a..fa03fd6c9d2 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppxref.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppxref.c @@ -9,8 +9,8 @@ ppxref * ppxref_create (ppdoc *pdf, size_t initsize, size_t xrefoffset) if (initsize == 0) // unknown initsize = PPXREF_MAP_INIT; - xref = (ppxref *)ppheap_take(&pdf->heap, sizeof(ppxref) + initsize * sizeof(ppxsec)); - xref->sects = (ppxsec *)(xref + 1); + xref = (ppxref *)ppstruct_take(&pdf->heap, sizeof(ppxref)); + xref->sects = (ppxsec *)ppstruct_take(&pdf->heap, initsize * sizeof(ppxsec)); xref->size = 0; xref->space = initsize; xref->count = 0; @@ -19,22 +19,41 @@ ppxref * ppxref_create (ppdoc *pdf, size_t initsize, size_t xrefoffset) xref->prev = NULL; xref->pdf = pdf; xref->offset = xrefoffset; - //xref->crypt = NULL; return xref; } -ppxsec * ppxref_push_section (ppxref *xref, ppheap **pheap) +ppxsec * ppxref_push_section (ppxref *xref, ppheap *heap) { ppxsec *sects; if (xref->size < xref->space) return &xref->sects[xref->size++]; xref->space <<= 1; sects = xref->sects; - xref->sects = (ppxsec *)ppheap_take(pheap, xref->space * sizeof(ppxsec)); // waste but rare + xref->sects = (ppxsec *)ppstruct_take(heap, xref->space * sizeof(ppxsec)); // waste but rare memcpy(xref->sects, sects, xref->size * sizeof(ppxsec)); return &xref->sects[xref->size++]; } +/* When loading xref table, we don't know how many sections is there. We assume 16, which is + more than usual (waste). But if there is more, we double the size, wasting again. This + could be made better with a dedicated allocator for xref sections (heap or generic malloc). + Or an ephemeric malloced c-array stored in heap once ready (analogical to stack used for dicts/arrays). + For xref streams we have explicit num of sections. */ + +/* +void ppxref_done_sections (ppxref *xref, ppheap *heap) +{ // if xref->sects was initialized with mallocted array we could do + ppxsec *sects; + size_t size; + sects = xref->sects; + size = xref->size * sizeof(ppxsec); + xref->sects = (ppxsec *)ppstruct_take(heap, size); + memcpy(xref->sects, sects, size); + pp_free(sects); + xref->space = xref->size; +} +*/ + static void ppxref_sort_sects (ppxsec *left, ppxsec *right) { ppxsec *l, *r, *m, t; @@ -165,24 +184,24 @@ ppdict * ppxref_trailer (ppxref *xref) ppxref * ppdoc_xref (ppdoc *pdf) { - return pdf->xref; + return pdf->xref; } ppxref * ppxref_prev (ppxref *xref) { - return xref->prev; + return xref->prev; } ppdict * ppxref_catalog (ppxref *xref) { - ppdict *trailer; - return (trailer = ppxref_trailer(xref)) != NULL ? ppdict_rget_dict(trailer, "Root") : NULL; + ppdict *trailer; + return (trailer = ppxref_trailer(xref)) != NULL ? ppdict_rget_dict(trailer, "Root") : NULL; } ppdict * ppxref_info (ppxref *xref) { - ppdict *trailer; - return (trailer = ppxref_trailer(xref)) != NULL ? ppdict_rget_dict(trailer, "Info") : NULL; + ppdict *trailer; + return (trailer = ppxref_trailer(xref)) != NULL ? ppdict_rget_dict(trailer, "Info") : NULL; } ppref * ppxref_pages (ppxref *xref) diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppxref.h b/Build/source/texk/web2c/luatexdir/luapplib/src/ppxref.h index 86ab98a512a..fbb83beced6 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/ppxref.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/ppxref.h @@ -24,11 +24,11 @@ struct ppxref { ppxref *prev; // previous xref ppdoc *pdf; // parent pdf to access entries in linearized docs size_t offset; // file offset of xref - //ppcrypt *crypt; // per xref encryption state? + //ppcrypt *crypt; // per xref encryption state? }; ppxref * ppxref_create (ppdoc *pdf, size_t initsize, size_t xrefoffset); -ppxsec * ppxref_push_section (ppxref *xref, ppheap **pheap); +ppxsec * ppxref_push_section (ppxref *xref, ppheap *heap); int ppxref_sort (ppxref *xref); ppref * ppxref_find_local (ppxref *xref, ppuint refnumber); diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/README.md b/Build/source/texk/web2c/luatexdir/luapplib/src/util/README.md new file mode 100644 index 00000000000..209bced0082 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/README.md @@ -0,0 +1,8 @@ +# pplib util
+
+This part is a toolbox. Contains utilities that are used by `pplib`
+but aren't tightly related to `PDF`. I use the toolbox in different
+projects and repos. It is important to me to keep this part in a perfect
+sync, at the cost of some redundant code (not used in `pplib`).
+`pplib` is hopefully not a subject for eternal development, so once
+it become final, we will make some cleanups here.
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilbasexx.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilbasexx.c index 6fdd6fb58c5..1c65b1ec399 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilbasexx.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilbasexx.c @@ -11,7 +11,7 @@ struct basexx_state { int tail[5]; int flush; }; -
+ struct runlength_state { int run; int flush; @@ -19,14 +19,7 @@ struct runlength_state { uint8_t *pos; }; -struct eexec_state { - int key; - int flush; - int binary; - int c1; - size_t line, maxline; /* ascii encoder only */ - const char *initbytes; -}; +typedef union { basexx_state *basexxstate; runlength_state *runlengthstate; void *voidstate; } basexx_state_pointer; // to avoid 'dereferencing type-puned ...' warnings /* config */ @@ -43,7 +36,8 @@ struct eexec_state { #define base64_eof(c) (c == '=' || c < 0) #define basexx_nl '\x0A' -#define put_nl(O, line, maxline, n) ((void)((line += n) > maxline && ((line = n), iof_set(O, basexx_nl)))) +//#define put_nl(O, line, maxline, n) ((void)((line += n) > maxline && ((line = n), iof_set(O, basexx_nl)))) // assignment in conditional warning +#define put_nl(O, line, maxline, n) do { line += n; if (line > maxline) line = n; iof_set(O, basexx_nl); } while (0) /* tail macros */ @@ -230,11 +224,11 @@ int base16_getc (iof *I) do { c2 = iof_get(I); } while (ignored(c2)); if (base16_eof(c2)) { - if ((c1 = base16_lookup[c1]) == -1) + if ((c1 = base16_value(c1)) < 0) return IOFERR; return c1<<4; } - if ((c1 = base16_lookup[c1]) == -1 || (c2 = base16_lookup[c2]) == -1) + if ((c1 = base16_value(c1)) < 0 || (c2 = base16_value(c2)) < 0) return IOFERR; return (c1<<4)|c2; } @@ -265,12 +259,12 @@ iof_status base16_decode (iof *I, iof *O) do { c2 = iof_get(I); } while (ignored(c2)); if (base16_eof(c2)) { - if ((c1 = base16_lookup[c1]) == -1) + if ((c1 = base16_value(c1)) < 0) return IOFERR; iof_set(O, c1<<4); // c2 := '0' return IOFEOF; } - if ((c1 = base16_lookup[c1]) == -1 || (c2 = base16_lookup[c2]) == -1) + if ((c1 = base16_value(c1)) < 0 || (c2 = base16_value(c2)) < 0) return IOFERR; iof_set(O, (c1<<4)|c2); } @@ -300,14 +294,14 @@ iof_status base16_decode_state (iof *I, iof *O, basexx_state *state) set_tail1(state, c1); /* set tail to let the caller display invalid chars */ if (state->flush) { - if ((c1 = base16_lookup[c1]) == -1) + if ((c1 = base16_value(c1)) < 0) return IOFERR; iof_set(O, c1<<4); // c2 := '0' return IOFEOF; } return IOFEMPTY; } - if ((d1 = base16_lookup[c1]) == -1 || (d2 = base16_lookup[c2]) == -1) + if ((d1 = base16_value(c1)) < 0 || (d2 = base16_value(c2)) < 0) { set_tail2(state, c1, c2); return IOFERR; @@ -340,6 +334,8 @@ const int base64_lookup[] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; +#define base64_value(c) base64_lookup[(uint8_t)(c)] + #define base64_digit1(c1) base64_alphabet[c1>>2] #define base64_digit2(c1, c2) base64_alphabet[((c1&3)<<4)|(c2>>4)] #define base64_digit3(c2, c3) base64_alphabet[((c2&15)<<2)|(c3>>6)] @@ -517,10 +513,28 @@ iof_status base64_encode_state_ln (iof *I, iof *O, basexx_state *state) return (state->flush ? IOFEOF : IOFEMPTY); byte1: if ((c2 = iof_get(I)) < 0) - return (state->flush ? (put_nl(O, state->line, state->maxline, 2), base64_encode_tail1(O, c1), IOFEOF) : (set_tail1(state, c1), IOFEMPTY)); + { + if (state->flush) + { + put_nl(O, state->line, state->maxline, 2); + base64_encode_tail1(O, c1); + return IOFEOF; + } + set_tail1(state, c1); + return IOFEMPTY; + } byte2: if ((c3 = iof_get(I)) < 0) - return (state->flush ? (put_nl(O, state->line, state->maxline, 3), base64_encode_tail2(O, c1, c2), IOFEOF) : (set_tail2(state, c1, c2), IOFEMPTY)); + { + if (state->flush) + { + put_nl(O, state->line, state->maxline, 3); + base64_encode_tail2(O, c1, c2); + return IOFEOF; + } + set_tail2(state, c1, c2); + return IOFEMPTY; + } put_nl(O, state->line, state->maxline, 4); base64_encode_word(O, c1, c2, c3); } @@ -552,7 +566,7 @@ iof_status base64_decode (iof *I, iof *O) do { c3 = iof_get(I); } while (ignored(c3)); if (base64_eof(c3)) { - if ((c1 = base64_lookup[c1]) == -1 || (c2 = base64_lookup[c2]) == -1) + if ((c1 = base64_value(c1)) < 0 || (c2 = base64_value(c2)) < 0) return IOFERR; base64_decode_tail2(O, c1, c2); return IOFEOF; @@ -560,13 +574,13 @@ iof_status base64_decode (iof *I, iof *O) do { c4 = iof_get(I); } while (ignored(c4)); if (base64_eof(c4)) { - if ((c1 = base64_lookup[c1]) == -1 || (c2 = base64_lookup[c2]) == -1 || (c3 = base64_lookup[c3]) == -1) + if ((c1 = base64_value(c1)) < 0 || (c2 = base64_value(c2)) < 0 || (c3 = base64_value(c3)) < 0) return IOFERR; base64_decode_tail3(O, c1, c2, c3); return IOFEOF; } - if ((c1 = base64_lookup[c1]) == -1 || (c2 = base64_lookup[c2]) == -1 || - (c3 = base64_lookup[c3]) == -1 || (c4 = base64_lookup[c4]) == -1) + if ((c1 = base64_value(c1)) < 0 || (c2 = base64_value(c2)) < 0 || + (c3 = base64_value(c3)) < 0 || (c4 = base64_value(c4)) < 0) return IOFERR; base64_decode_word(O, c1, c2, c3, c4); } @@ -604,7 +618,7 @@ iof_status base64_decode_state (iof *I, iof *O, basexx_state *state) set_tail2(state, c1, c2); if (state->flush) { - if ((c1 = base64_lookup[c1]) == -1 || (c2 = base64_lookup[c2]) == -1) + if ((c1 = base64_value(c1)) < 0 || (c2 = base64_value(c2)) < 0) return IOFERR; base64_decode_tail2(O, c1, c2); return IOFEOF; @@ -619,7 +633,7 @@ iof_status base64_decode_state (iof *I, iof *O, basexx_state *state) set_tail3(state, c1, c2, c3); if (state->flush) { - if ((c1 = base64_lookup[c1]) == -1 || (c2 = base64_lookup[c2]) == -1 || (c3 = base64_lookup[c3]) == -1) + if ((c1 = base64_value(c1)) < 0 || (c2 = base64_value(c2)) < 0 || (c3 = base64_value(c3)) < 0) return IOFERR; base64_decode_tail3(O, c1, c2, c3); return IOFEOF; @@ -627,8 +641,8 @@ iof_status base64_decode_state (iof *I, iof *O, basexx_state *state) else return IOFEMPTY; } - if ((d1 = base64_lookup[c1]) == -1 || (d2 = base64_lookup[c2]) == -1 || - (d3 = base64_lookup[c3]) == -1 || (d4 = base64_lookup[c4]) == -1) + if ((d1 = base64_value(c1)) < 0 || (d2 = base64_value(c2)) < 0 || + (d3 = base64_value(c3)) < 0 || (d4 = base64_value(c4)) < 0) { set_tail4(state, c1, c2, c3, c4); return IOFERR; @@ -661,6 +675,8 @@ const int base85_lookup[] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; +#define base85_value(c) base85_lookup[(uint8_t)(c)] + #define base85_encode_word(O, code) \ (*(O->pos+4) = '!' + code%85, code /= 85, *(O->pos+3) = '!' + code%85, code /= 85, \ *(O->pos+2) = '!' + code%85, code /= 85, *(O->pos+1) = '!' + code%85, code /= 85, \ @@ -1038,7 +1054,7 @@ iof_status base85_decode (iof *I, iof *O) do { c3 = iof_get(I); } while (ignored(c3)); if (base85_eof(c3)) { - if ((c1 = base85_lookup[c1]) == -1 || (c2 = base85_lookup[c2]) == -1) + if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0) return IOFERR; code = base85_code(c1, c2, 84, 84, 84); /* padding with 'u' (117); 117-33 = 84 */ iof_set(O, code>>24); @@ -1047,7 +1063,7 @@ iof_status base85_decode (iof *I, iof *O) do { c4 = iof_get(I); } while (ignored(c4)); if (base85_eof(c4)) { - if ((c1 = base85_lookup[c1]) == -1 || (c2 = base85_lookup[c2]) == -1 || (c3 = base85_lookup[c3]) == -1) + if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0 || (c3 = base85_value(c3)) < 0) return IOFERR; code = base85_code(c1, c2, c3, 84, 84); iof_set2(O, code>>24, (code>>16)&255); @@ -1056,15 +1072,15 @@ iof_status base85_decode (iof *I, iof *O) do { c5 = iof_get(I); } while (ignored(c5)); if (base85_eof(c5)) { - if ((c1 = base85_lookup[c1]) == -1 || (c2 = base85_lookup[c2]) == -1 || - (c3 = base85_lookup[c3]) == -1 || (c4 = base85_lookup[c4]) == -1) + if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0 || + (c3 = base85_value(c3)) < 0 || (c4 = base85_value(c4)) < 0) return IOFERR; code = base85_code(c1, c2, c3, c4, 84); iof_set3(O, code>>24, (code>>16)&255, (code>>8)&255); return IOFEOF; } - if ((c1 = base85_lookup[c1]) == -1 || (c2 = base85_lookup[c2]) == -1 || (c3 = base85_lookup[c3]) == -1 || - (c4 = base85_lookup[c4]) == -1 || (c5 = base85_lookup[c5]) == -1) + if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0 || (c3 = base85_value(c3)) < 0 || + (c4 = base85_value(c4)) < 0 || (c5 = base85_value(c5)) < 0) return IOFERR; code = base85_code(c1, c2, c3, c4, c5); iof_set4(O, code>>24, (code>>16)&255, (code>>8)&255, code&255); @@ -1116,7 +1132,7 @@ iof_status base85_decode_state (iof *I, iof *O, basexx_state *state) set_tail2(state, c1, c2); if (state->flush) { - if ((c1 = base85_lookup[c1]) == -1 || (c2 = base85_lookup[c2]) == -1) + if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0) return IOFERR; code = base85_code(c1, c2, 84, 84, 84); iof_set(O, code>>24); @@ -1131,7 +1147,7 @@ iof_status base85_decode_state (iof *I, iof *O, basexx_state *state) set_tail3(state, c1, c2, c3); if (state->flush) { - if ((c1 = base85_lookup[c1]) == -1 || (c2 = base85_lookup[c2]) == -1 || (c3 = base85_lookup[c3]) == -1) + if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0 || (c3 = base85_value(c3)) < 0) return IOFERR; code = base85_code(c1, c2, c3, 84, 84); iof_set2(O, code>>24, (code>>16)&255); @@ -1146,8 +1162,8 @@ iof_status base85_decode_state (iof *I, iof *O, basexx_state *state) set_tail4(state, c1, c2, c3, c4); if (state->flush) { - if ((c1 = base85_lookup[c1]) == -1 || (c2 = base85_lookup[c2]) == -1 || - (c3 = base85_lookup[c3]) == -1 || (c4 = base85_lookup[c4]) == -1) + if ((c1 = base85_value(c1)) < 0 || (c2 = base85_value(c2)) < 0 || + (c3 = base85_value(c3)) < 0 || (c4 = base85_value(c4)) < 0) return IOFERR; code = base85_code(c1, c2, c3, c4, 84); iof_set3(O, code>>24, (code>>16)&255, (code>>8)&255); @@ -1155,8 +1171,8 @@ iof_status base85_decode_state (iof *I, iof *O, basexx_state *state) } return IOFEMPTY; } - if ((d1 = base85_lookup[c1]) == -1 || (d2 = base85_lookup[c2]) == -1 || (d3 = base85_lookup[c3]) == -1 || - (d4 = base85_lookup[c4]) == -1 || (d5 = base85_lookup[c5]) == -1) + if ((d1 = base85_value(c1)) < 0 || (d2 = base85_value(c2)) < 0 || (d3 = base85_value(c3)) < 0 || + (d4 = base85_value(c4)) < 0 || (d5 = base85_value(c5)) < 0) { set_tail5(state, c1, c2, c3, c4, c5); return IOFERR; @@ -1182,7 +1198,7 @@ iof_status runlength_encode (iof *I, iof *O) { register int c1, c2, run = -1; uint8_t *pos; - c1 = 0; /* avoid warning */ + c1 = 0, c2 = 0; /* avoid warning */ while (iof_ensure(O, 1+128+1)) { /* ensured space for single length byte, up to 128 bytes to be copied, possible eod marker */ pos = O->pos++; @@ -1192,7 +1208,7 @@ iof_status runlength_encode (iof *I, iof *O) if ((c1 = iof_get(I)) < 0) return (*pos = 128, IOFEOF); run = 0; - // fall through + FALLTHRU // fall through case 0: /* `repeat' state; get another byte and compare */ if ((c2 = iof_get(I)) < 0) return (*pos = 0, iof_set2(O, c1, 128), IOFEOF); @@ -1236,7 +1252,7 @@ iof_status runlength_encode_state (iof *I, iof *O, runlength_state *state) if ((state->c1 = iof_get(I)) < 0) return (state->flush ? (*state->pos = 128, IOFEOF) : IOFEMPTY); state->run = 0; - // fall through + FALLTHRU // fall through case 0: /* `repeat' state; get another byte and compare */ if ((state->c2 = iof_get(I)) < 0) return (state->flush ? (*state->pos = 0, iof_set2(O, state->c1, 128), IOFEOF) : IOFEMPTY); @@ -1376,305 +1392,6 @@ iof_status runlength_decode_state (iof *I, iof *O, runlength_state *state) // return IOFFULL; } -/* eexec stream filter, type1 fonts spec page 63 */ - -void eexec_state_init_ln (eexec_state *state, size_t line, size_t maxline, const char *initbytes) -{ - state->key = -1; - state->flush = 0; - state->binary = maxline > 0; - state->c1 = -1; - state->line = line; - state->maxline = maxline; - state->initbytes = initbytes; -} - -#define eexec_getc(I, c1) if ((c1 = iof_get(I)) < 0) return c1 -#define eexec_key(key, c1) (key = ((((c1) + key)*52845 + 22719) & 65535)) -#define eexec_decipher(key, c1, c) (c = ((c1)^(key>>8)), eexec_key(key, c1)) -#define eexec_encipher(key, c1, c) (c = ((c1)^(key>>8)), eexec_key(key, c)) - -#ifndef lps_ignored_char -# define lps_ignored_char(c) (c == 0x20 || c == 0x0A || c == 0x0C || c == 0x0D || c == 0x09 || c == 0x00) -#endif - -#define eexec_getx_(I, c) \ - do { c = iof_get(I); } while (lps_ignored_char(c)); \ - if (c < 0) return IOFEOF; \ - if ((c = base16_lookup[c]) < 0) return IOFERR - -#define eexec_getx(I, c1, c2) eexec_getx_(I, c1); \ - do { c2 = iof_get(I); } while (lps_ignored_char(c2)); \ - if (c2 < 0) c2 = 0; else \ - if ((c2 = base16_lookup[c2]) < 0) return IOFERR - -static int eexec_decode_init (iof *I, int *key, int *binary) -{ - int c1, c2, c3, c4; - *key = 55665; - eexec_getc(I, c1); - eexec_getc(I, c2); - eexec_getc(I, c3); - eexec_getc(I, c4); /* four head bytes */ - - /* eexec data has no explicit data termination. The caller of eexec_decode() should ensure that either - the input iof allows to read no more then necessary, or the output has no more space then 512 bytes, - to land safely somewhere in 512 bytes that probably follows eexec */ - - *binary = (base16_lookup[c1] < 0 || base16_lookup[c2] < 0 || - base16_lookup[c3] < 0 || base16_lookup[c4] < 0); - if (*binary) - { /* gobble 4 random bytes keeping decipher key up-to-date */ - eexec_key(*key, c1); eexec_key(*key, c2); - eexec_key(*key, c3); eexec_key(*key, c4); - } - else /* pfa/postscript only, pdf requires binary eexec form */ - { /* gobble 4 random bytes (8 hex digits) keeping decipher key up-to-date */ - c1 = base16_lookup[c1], c2 = base16_lookup[c2], c3 = base16_lookup[c3], c4 = base16_lookup[c4]; - eexec_key(*key, (c1<<4)|c2); eexec_key(*key, (c3<<4)|c4); /* dummy bytes 1, 2 */ - eexec_getx(I, c1, c2); eexec_getx(I, c3, c4); - eexec_key(*key, (c1<<4)|c2); eexec_key(*key, (c3<<4)|c4); /* dummy bytes 3, 4 */ - } - return 0; -} - -iof_status eexec_decode (iof *I, iof *O) -{ - int c, c1, c2, key, binary, status; - if ((status = eexec_decode_init(I, &key, &binary)) < 0) - return status; - if (binary) - { - while (iof_ensure(O, 1)) - { - eexec_getc(I, c1); - eexec_decipher(key, c1, c); - iof_set(O, c); - } - } - else - { - while (iof_ensure(O, 1)) - { - eexec_getx(I, c1, c2); - eexec_decipher(key, (c1<<4)|c2, c); - iof_set(O, c); - } - } - return IOFFULL; -} - -iof_status eexec_decode_state (iof *I, iof *O, eexec_state *state) -{ - register int c, c1, c2, status; - if (state->key == -1) /* initial state */ - if ((status = eexec_decode_init(I, &state->key, &state->binary)) < 0) - return status; - if (state->binary) - { - while (iof_ensure(O, 1)) - { - if ((c1 = iof_get(I)) < 0) - return (state->flush ? IOFEOF : IOFEMPTY); - else if (c1 < 0) - return c1; - eexec_decipher(state->key, c1, c); - iof_set(O, c); - } - } - else - { - if (state->c1 > -1) - { - c1 = state->c1; - state->c1 = -1; - goto byte2; - } - while (iof_ensure(O, 1)) - { - eexec_getx_(I, c1); - byte2: - do { c2 = iof_get(I); } while (lps_ignored_char(c2)); - if (c2 < 0) // odd number of hex bytes? hmm... assume c2 is zero - { - if (state->flush) - { - eexec_decipher(state->key, (c1<<4), c); - iof_set(O, c); - return IOFEOF; - } - state->c1 = c1; - return IOFEMPTY; - } - else if (c2 < 0) - return c2; - if ((c2 = base16_lookup[c2]) < 0) - return IOFERR; - eexec_decipher(state->key, (c1<<4)|c2, c); - iof_set(O, c); - } - } - return IOFFULL; -} - -#define EEXEC_INIT_BYTES "" - -iof_status eexec_encode (iof *I, iof *O, size_t line, size_t maxline) -{ - int c1, c, key; - const char *p; - - key = 55665; - p = EEXEC_INIT_BYTES; - if (maxline == 0) - { - if (!iof_ensure(O, 4)) - return IOFFULL; - eexec_encipher(key, p[0], c); iof_set(O, c); - eexec_encipher(key, p[1], c); iof_set(O, c); - eexec_encipher(key, p[2], c); iof_set(O, c); - eexec_encipher(key, p[3], c); iof_set(O, c); - while (iof_ensure(O, 1)) - { - eexec_getc(I, c1); - eexec_encipher(key, c1, c); - iof_set(O, c); - } - } - else - { - if (!iof_ensure(O, 8 + 1)) - return IOFFULL; - eexec_encipher(key, p[0], c); put_nl(O, line, maxline, 2); iof_set_uc_hex(O, c); - eexec_encipher(key, p[1], c); put_nl(O, line, maxline, 2); iof_set_uc_hex(O, c); - eexec_encipher(key, p[2], c); put_nl(O, line, maxline, 2); iof_set_uc_hex(O, c); - eexec_encipher(key, p[3], c); put_nl(O, line, maxline, 2); iof_set_uc_hex(O, c); - while (iof_ensure(O, 2 + 1)) - { - eexec_getc(I, c1); - eexec_encipher(key, c1, c); - put_nl(O, line, maxline, 2); - iof_set_uc_hex(O, c); - } - } - return IOFFULL; -} - -iof_status eexec_encode_state (iof *I, iof *O, eexec_state *state) -{ - int c, c1; - const char *p; - - if (state->key == -1) - { - p = state->initbytes != NULL ? state->initbytes : EEXEC_INIT_BYTES; - if (state->binary) - { - if (!iof_ensure(O, 4)) - return IOFFULL; - state->key = 55665; - eexec_encipher(state->key, p[0], c); iof_set(O, c); - eexec_encipher(state->key, p[1], c); iof_set(O, c); - eexec_encipher(state->key, p[2], c); iof_set(O, c); - eexec_encipher(state->key, p[3], c); iof_set(O, c); - } - else - { - if (!iof_ensure(O, 8 + 1)) - return IOFFULL; - state->key = 55665; - eexec_encipher(state->key, p[0], c); put_nl(O, state->line, state->maxline, 2); iof_set_uc_hex(O, c); - eexec_encipher(state->key, p[1], c); put_nl(O, state->line, state->maxline, 2); iof_set_uc_hex(O, c); - eexec_encipher(state->key, p[2], c); put_nl(O, state->line, state->maxline, 2); iof_set_uc_hex(O, c); - eexec_encipher(state->key, p[3], c); put_nl(O, state->line, state->maxline, 2); iof_set_uc_hex(O, c); - } - } - if (state->binary) - { - while (iof_ensure(O, 1)) - { - if ((c1 = iof_get(I)) < 0) - return c1 < 0 ? (state->flush ? IOFEOF : IOFEMPTY) : c1; - eexec_encipher(state->key, c1, c); - iof_set(O, c); - } - } - else - { - while (iof_ensure(O, 2 + 1)) - { - if ((c1 = iof_get(I)) < 0) - return c1 < 0 ? (state->flush ? IOFEOF : IOFEMPTY) : c1; - eexec_encipher(state->key, c1, c); - put_nl(O, state->line, state->maxline, 2); - iof_set_uc_hex(O, c); - } - } - return IOFFULL; -} - -/* -Type1 charstrings are encoded/decoded in the same way, except that: -- initial key is 4330 -- initbytes might be other then 4; /lenIV key in Private dict -Type1 spec page 63. In practise we don't need iof interface here, -we always apply the codec in place. -*/ - -#define type1chstr_key(key, c1) (key = ((((c1) + key)*52845 + 22719) & 65535)) -#define type1chstr_decipher(key, c1, c) (c = ((c1)^(key>>8)), type1chstr_key(key, c1)) -#define type1chstr_encipher(key, c1, c) (c = ((c1)^(key>>8)), type1chstr_key(key, c)) - -int type1_charstring_decode (void *data, size_t size, void *outdata, uint8_t leniv) -{ /* data and outdata may be the same, output size is always size - leniv */ - uint8_t *input = (uint8_t *)data, *output = (uint8_t *)outdata; - size_t i; - int c, c1, key; - - if (size < 4) - return 0; - key = 4330; - for (i = 0; i < leniv; ++i) - { - c1 = input[i]; - type1chstr_key(key, c1); - } - for ( ; i < size; ++i) - { - c1 = input[i]; - type1chstr_decipher(key, c1, c); - output[i - leniv] = c; - } - return 1; -} - -#define TYPE1_CHSTR_INIT_BYTES EEXEC_INIT_BYTES - -int type1_charstring_encode (void *data, size_t size, void *outdata, uint8_t leniv) -{ /* outdata may be data - leniv, output size is always size + leniv */ - uint8_t *input = (uint8_t *)data, *output = (uint8_t *)outdata; - size_t i, j; - int c, c1, key; - - key = 4330; - for (i = 0, j = 0; i < leniv; ++i) - { - c1 = TYPE1_CHSTR_INIT_BYTES[j]; - //type1chstr_key(key, c1); - type1chstr_encipher(key, c1, c); - if (++j == 4) - j = 0; - output[i] = c; - } - for (i = 0; i < size; ++i) - { - c1 = input[i]; - type1chstr_encipher(key, c1, c); - output[i + leniv] = c; - } - return 1; -} - /* filters */ // base16 decoder function @@ -1720,7 +1437,7 @@ static size_t base16_encoder (iof *F, iof_mode mode) { case IOFFLUSH: state->flush = 1; - // fall through + FALLTHRU // fall through case IOFWRITE: F->end = F->pos; F->pos = F->buf; @@ -1780,7 +1497,7 @@ static size_t base64_encoder (iof *F, iof_mode mode) { case IOFFLUSH: state->flush = 1; - // fall through + FALLTHRU // fall through case IOFWRITE: F->end = F->pos; F->pos = F->buf; @@ -1840,7 +1557,7 @@ static size_t base85_encoder (iof *F, iof_mode mode) { case IOFFLUSH: state->flush = 1; - // fall through + FALLTHRU // fall through case IOFWRITE: F->end = F->pos; F->pos = F->buf; @@ -1900,7 +1617,7 @@ static size_t runlength_encoder (iof *F, iof_mode mode) { case IOFFLUSH: state->flush = 1; - // fall through + FALLTHRU // fall through case IOFWRITE: F->end = F->pos; F->pos = F->buf; @@ -1917,66 +1634,6 @@ static size_t runlength_encoder (iof *F, iof_mode mode) return 0; } -// eexec decoder function - -static size_t eexec_decoder (iof *F, iof_mode mode) -{ - eexec_state *state; - iof_status status; - size_t tail; - - switch(mode) - { - case IOFLOAD: - case IOFREAD: - if (F->flags & IOF_STOPPED) - return 0; - tail = iof_tail(F); - F->pos = F->buf + tail; - F->end = F->buf + F->space; - state = iof_filter_state(eexec_state *, F); - do { - status = eexec_decode_state(F->next, F, state); - } while (mode == IOFLOAD && status == IOFFULL && iof_resize_buffer(F)); - return iof_decoder_retval(F, "eexec", status); - case IOFCLOSE: - iof_free(F); - return 0; - default: - break; - } - return 0; -} - -// eexec encoder function - -static size_t eexec_encoder (iof *F, iof_mode mode) -{ - eexec_state *state; - iof_status status; - - state = iof_filter_state(eexec_state *, F); - switch (mode) - { - case IOFFLUSH: - state->flush = 1; - // fall through - case IOFWRITE: - F->end = F->pos; - F->pos = F->buf; - status = eexec_encode_state(F, F->next, state); - return iof_encoder_retval(F, "eexec", status); - case IOFCLOSE: - if (!state->flush) - eexec_encoder(F, IOFFLUSH); - iof_free(F); - return 0; - default: - break; - } - return 0; -} - // int iof_filter_basexx_encoder_ln (iof *F, size_t line, size_t maxline) @@ -1997,21 +1654,21 @@ int iof_filter_basexx_encoder_ln (iof *F, size_t line, size_t maxline) iof * iof_filter_base16_decoder (iof *N) { iof *I; - basexx_state *state; - I = iof_filter_reader(base16_decoder, sizeof(basexx_state), &state); + basexx_state_pointer P; + I = iof_filter_reader(base16_decoder, sizeof(basexx_state), &P.voidstate); iof_setup_next(I, N); - basexx_state_init(state); - state->flush = 1; // means N is supposed to be continuous input + basexx_state_init(P.basexxstate); + P.basexxstate->flush = 1; // means N is supposed to be continuous input return I; } iof * iof_filter_base16_encoder (iof *N) { iof *O; - basexx_state *state; - O = iof_filter_writer(base16_encoder, sizeof(basexx_state), &state); + basexx_state_pointer P; + O = iof_filter_writer(base16_encoder, sizeof(basexx_state), &P.voidstate); iof_setup_next(O, N); - basexx_state_init(state); + basexx_state_init(P.basexxstate); return O; } @@ -2020,21 +1677,21 @@ iof * iof_filter_base16_encoder (iof *N) iof * iof_filter_base64_decoder (iof *N) { iof *I; - basexx_state *state; - I = iof_filter_reader(base64_decoder, sizeof(basexx_state), &state); + basexx_state_pointer P; + I = iof_filter_reader(base64_decoder, sizeof(basexx_state), &P.voidstate); iof_setup_next(I, N); - basexx_state_init(state); - state->flush = 1; + basexx_state_init(P.basexxstate); + P.basexxstate->flush = 1; return I; } iof * iof_filter_base64_encoder (iof *N) { iof *O; - basexx_state *state; - O = iof_filter_writer(base64_encoder, sizeof(basexx_state), &state); + basexx_state_pointer P; + O = iof_filter_writer(base64_encoder, sizeof(basexx_state), &P.voidstate); iof_setup_next(O, N); - basexx_state_init(state); + basexx_state_init(P.basexxstate); return O; } @@ -2043,21 +1700,21 @@ iof * iof_filter_base64_encoder (iof *N) iof * iof_filter_base85_decoder (iof *N) { iof *I; - basexx_state *state; - I = iof_filter_reader(base85_decoder, sizeof(basexx_state), &state); + basexx_state_pointer P; + I = iof_filter_reader(base85_decoder, sizeof(basexx_state), &P.voidstate); iof_setup_next(I, N); - basexx_state_init(state); - state->flush = 1; + basexx_state_init(P.basexxstate); + P.basexxstate->flush = 1; return I; } iof * iof_filter_base85_encoder (iof *N) { iof *O; - basexx_state *state; - O = iof_filter_writer(base85_encoder, sizeof(basexx_state), &state); + basexx_state_pointer P; + O = iof_filter_writer(base85_encoder, sizeof(basexx_state), &P.voidstate); iof_setup_next(O, N); - basexx_state_init(state); + basexx_state_init(P.basexxstate); return O; } @@ -2066,43 +1723,20 @@ iof * iof_filter_base85_encoder (iof *N) iof * iof_filter_runlength_decoder (iof *N) { iof *I; - runlength_state *state; - I = iof_filter_reader(runlength_decoder, sizeof(runlength_state), &state); + basexx_state_pointer P; + I = iof_filter_reader(runlength_decoder, sizeof(runlength_state), &P.voidstate); iof_setup_next(I, N); - runlength_state_init(state); - state->flush = 1; + runlength_state_init(P.runlengthstate); + P.runlengthstate->flush = 1; return I; } iof * iof_filter_runlength_encoder (iof *N) { iof *O; - runlength_state *state; - O = iof_filter_writer(runlength_encoder, sizeof(runlength_state), &state); - iof_setup_next(O, N); - runlength_state_init(state); - return O; -} - -/* eexec stream filter, type1 fonts spec p. 63 */ - -iof * iof_filter_eexec_decoder (iof *N) -{ - iof *I; - eexec_state *state; - I = iof_filter_reader(eexec_decoder, sizeof(eexec_state), &state); - iof_setup_next(I, N); - eexec_state_init(state); - state->flush = 1; - return I; -} - -iof * iof_filter_eexec_encoder (iof *N) -{ - iof *O; - eexec_state *state; - O = iof_filter_writer(eexec_encoder, sizeof(eexec_state), &state); + basexx_state_pointer P; + O = iof_filter_writer(runlength_encoder, sizeof(runlength_state), &P.voidstate); iof_setup_next(O, N); - eexec_state_init(state); + runlength_state_init(P.runlengthstate); return O; } diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilbasexx.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilbasexx.h index 52aac3772ca..81891b549fb 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilbasexx.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilbasexx.h @@ -92,24 +92,6 @@ iof_status runlength_encode_state (iof *I, iof *O, runlength_state *state); iof_status runlength_decode (iof *I, iof *O); iof_status runlength_decode_state (iof *I, iof *O, runlength_state *state); -/* eexec */ - -typedef struct eexec_state eexec_state; - -#define EEXEC_MAXLINE 80 - -void eexec_state_init_ln (eexec_state *state, size_t line, size_t maxline, const char *initbytes); -#define eexec_state_init(state) eexec_state_init_ln(state, 0, EEXEC_MAXLINE, NULL) - -iof_status eexec_decode (iof *I, iof *O); -iof_status eexec_decode_state (iof *I, iof *O, eexec_state *state); - -iof_status eexec_encode (iof *I, iof *O, size_t line, size_t maxline); -iof_status eexec_encode_state (iof *I, iof *O, eexec_state *state); - -iof_status type1_charstring_decode (void *data, size_t size, void *outdata, uint8_t leniv); -iof_status type1_charstring_encode (void *data, size_t size, void *outdata, uint8_t leniv); - /* filters */ int iof_filter_basexx_encoder_ln (iof *N, size_t line, size_t maxline); @@ -126,8 +108,4 @@ iof * iof_filter_base85_encoder (iof *N); iof * iof_filter_runlength_decoder (iof *N); iof * iof_filter_runlength_encoder (iof *N); -iof * iof_filter_eexec_decoder (iof *N); -iof * iof_filter_eexec_encoder (iof *N); - - #endif diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilcrypt.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilcrypt.c index 1750d01bd86..2c77e42a4c7 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilcrypt.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilcrypt.c @@ -232,8 +232,8 @@ static void aes_copy_xor (uint8_t *data, const uint8_t *input, const uint8_t *iv static void key_expansion (aes_state *state, const uint8_t *key) { - uint32_t i, j, k; - uint8_t t[4]; + uint32_t i, j; + uint8_t t[4], temp; uint8_t *keydata, keywords, columns; keywords = (uint8_t)(state->keylength >> 2); @@ -249,7 +249,6 @@ static void key_expansion (aes_state *state, const uint8_t *key) } /* others derived from the first */ - for(columns = AES_COLUMNS * (state->rounds + 1); i < columns; ++i) { for(j = 0; j < 4; ++j) @@ -257,11 +256,11 @@ static void key_expansion (aes_state *state, const uint8_t *key) if (i % keywords == 0) { /* rotate the 4 bytes in a word to the left once; [a0,a1,a2,a3] becomes [a1,a2,a3,a0] */ - k = t[0]; + temp = t[0]; t[0] = t[1]; t[1] = t[2]; t[2] = t[3]; - t[3] = k; + t[3] = temp; /* take a four-byte input word and apply the S-box to each of the four bytes to produce an output word */ t[0] = sbox[t[0]]; @@ -913,7 +912,7 @@ static size_t rc4_encoder (iof *F, iof_mode mode) { case IOFFLUSH: state->flush = 1; - // fall through + FALLTHRU // fall through case IOFWRITE: F->end = F->pos; F->pos = F->buf; @@ -975,7 +974,7 @@ static size_t aes_encoder (iof *F, iof_mode mode) { case IOFFLUSH: state->flush = 1; - // fall through + FALLTHRU // fall through case IOFWRITE: F->end = F->pos; F->pos = F->buf; @@ -996,32 +995,32 @@ static size_t aes_encoder (iof *F, iof_mode mode) iof * iof_filter_rc4_decoder (iof *N, const void *key, size_t keylength) { iof *I; - rc4_state *state; + crypt_state_pointer P; - I = iof_filter_reader(rc4_decoder, sizeof(rc4_state), &state); + I = iof_filter_reader(rc4_decoder, sizeof(rc4_state), &P.voidstate); iof_setup_next(I, N); - if (rc4_state_init(state, key, keylength) == NULL) + if (rc4_state_init(P.rc4state, key, keylength) == NULL) { iof_discard(I); return NULL; } - state->flush = 1; + P.rc4state->flush = 1; return I; } iof * iof_filter_rc4_encoder (iof *N, const void *key, size_t keylength) { iof *O; - rc4_state *state; + crypt_state_pointer P; - O = iof_filter_writer(rc4_encoder, sizeof(rc4_state), &state); + O = iof_filter_writer(rc4_encoder, sizeof(rc4_state), &P.voidstate); iof_setup_next(O, N); - if (rc4_state_init(state, key, keylength) == NULL) + if (rc4_state_init(P.rc4state, key, keylength) == NULL) { iof_discard(O); return NULL; } - // state->flush = 1; + // P.rc4state->flush = 1; return O; } @@ -1030,34 +1029,34 @@ iof * iof_filter_rc4_encoder (iof *N, const void *key, size_t keylength) iof * iof_filter_aes_decoder (iof *N, const void *key, size_t keylength) { iof *I; - aes_state *state; + crypt_state_pointer P; - I = iof_filter_reader(aes_decoder, sizeof(aes_state), &state); + I = iof_filter_reader(aes_decoder, sizeof(aes_state), &P.voidstate); iof_setup_next(I, N); - if (aes_decode_init(state, key, keylength) == NULL) + if (aes_decode_init(P.aesstate, key, keylength) == NULL) { iof_discard(I); return NULL; } - aes_pdf_mode(state); - state->flush = 1; + aes_pdf_mode(P.aesstate); + P.aesstate->flush = 1; return I; } iof * iof_filter_aes_encoder (iof *N, const void *key, size_t keylength) { iof *O; - aes_state *state; + crypt_state_pointer P; - O = iof_filter_writer(aes_encoder, sizeof(aes_state), &state); + O = iof_filter_writer(aes_encoder, sizeof(aes_state), &P.voidstate); iof_setup_next(O, N); - if (aes_encode_init(state, key, keylength) == NULL) + if (aes_encode_init(P.aesstate, key, keylength) == NULL) { iof_discard(O); return NULL; } - aes_pdf_mode(state); - // state->flush = 1; + aes_pdf_mode(P.aesstate); + // P.aesstate->flush = 1; return O; } @@ -1092,14 +1091,14 @@ void aes_test (void) size_t inpsize, outsize; int flags = AES_NULL_PADDING; - //////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////// //#define ENCODETO output #define ENCODETO input // inplace inpsize = 64; memcpy(input, inp, inpsize); - show(input, inpsize, '>', '>'); + show(input, inpsize, '>', '>'); outsize = aes_encode_data(input, inpsize, ENCODETO, key, 16, iv, flags); show(ENCODETO, outsize, '<', '<'); if (outsize == inpsize && memcmp(ENCODETO, out, outsize) == 0) @@ -1107,7 +1106,7 @@ void aes_test (void) else printf("ENCODER FAILURE\n"); - //////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////// //#define DECODETO input #define DECODETO output // in place @@ -1115,7 +1114,7 @@ void aes_test (void) outsize = 64; memcpy(output, out, outsize); show(output, outsize, '<', '<'); - inpsize = aes_decode_data(output, outsize, DECODETO, key, 16, iv, flags); + inpsize = aes_decode_data(output, outsize, DECODETO, key, 16, iv, flags); show(DECODETO, inpsize, '>', '>'); if (inpsize == outsize && memcmp(DECODETO, inp, inpsize) == 0) printf("DECODER SUCCESS\n"); diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilcrypt.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilcrypt.h index e5bf53cc5ce..e5bf53cc5ce 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilcrypt.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilcrypt.h diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilcryptdef.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilcryptdef.h index 02d70aa5ef6..d43ea2e5b53 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilcryptdef.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilcryptdef.h @@ -27,4 +27,6 @@ struct aes_state { int flags; }; +typedef union { rc4_state *rc4state; aes_state *aesstate; void *voidstate; } crypt_state_pointer; // to avoid 'dereferencing type-puned ...' warnings + #endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utildecl.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utildecl.h index 94ef73413eb..b11e5b88432 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utildecl.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utildecl.h @@ -10,7 +10,7 @@ UTILEXE - when building .exe to import symbols from .dll #if defined (_WIN32) || defined(_WIN64) # ifdef UTILDLL # define UTILAPI __declspec(dllexport) -# define UTILDEF __declspec(dllexport) +# define UTILDEF __declspec(dllexport) # else # ifdef UTILEXE # define UTILAPI __declspec(dllimport) diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilflate.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilflate.c index 8ecc240c9dc..27e44d409a1 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilflate.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilflate.c @@ -1,8 +1,9 @@ +#include <zlib.h> + #include "utilmem.h" #include "utillog.h" #include "utilflate.h" -#include <zlib.h> /* flate codec */ @@ -83,6 +84,8 @@ struct flate_state { int level; /* encoder compression level -1..9 */ }; +typedef union { flate_state *flatestate; void *voidstate; } flate_state_pointer; // to avoid 'dereferencing type-puned ...' warnings + enum { FLATE_IN, FLATE_OUT, @@ -271,7 +274,7 @@ static size_t flate_encoder (iof *F, iof_mode mode) { case IOFFLUSH: state->flush = 1; - // fall through + FALLTHRU // fall through case IOFWRITE: F->end = F->pos; F->pos = F->buf; @@ -292,25 +295,25 @@ static size_t flate_encoder (iof *F, iof_mode mode) iof * iof_filter_flate_decoder (iof *N) { iof *I; - flate_state *state; - I = iof_filter_reader(flate_decoder, sizeof(flate_state), &state); + flate_state_pointer P; + I = iof_filter_reader(flate_decoder, sizeof(flate_state), &P.voidstate); iof_setup_next(I, N); - if (flate_decoder_init(state) == NULL) + if (flate_decoder_init(P.flatestate) == NULL) { iof_discard(I); return NULL; } - state->flush = 1; + P.flatestate->flush = 1; return I; } iof * iof_filter_flate_encoder (iof *N) { iof *O; - flate_state *state; - O = iof_filter_writer(flate_encoder, sizeof(flate_state), &state); + flate_state_pointer P; + O = iof_filter_writer(flate_encoder, sizeof(flate_state), &P.voidstate); iof_setup_next(O, N); - if (flate_encoder_init(state) == NULL) + if (flate_encoder_init(P.flatestate) == NULL) { iof_discard(O); return NULL; diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilflate.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilflate.h index 09bdd666112..09bdd666112 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilflate.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilflate.h diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilfpred.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilfpred.c index 5418a520151..9203c5e0742 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilfpred.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilfpred.c @@ -58,7 +58,6 @@ that are permanently \0. #define MAX_COMPONENTS 8 -/*typedef */ struct predictor_state { int default_predictor; /* default predictor indicator */ int current_predictor; /* current predictor, possibly taken from algorithm marker in PNG data */ @@ -66,7 +65,7 @@ struct predictor_state { int compbits; /* number of bits per component (/DecodeParms << /BitsPerComponent ... >>) */ int components; /* number of components (/DecodeParms << /Colors ... >>) */ uint8_t *buffer; /* temporary private buffer area */ - uint8_t *rowin; /* an input row buffer position */ + uint8_t *rowin; /* an input row buffer position */ int rowsize; /* size of a current scanline in bytes (rounded up) */ int rowend; /* an input buffer end position */ int rowindex; /* an output buffer position */ @@ -91,7 +90,9 @@ struct predictor_state { }; int flush; int status; -} ; /*predictor_state;*/ +}; + +typedef union { predictor_state *predictorstate; void *voidstate; } predictor_state_pointer; // to avoid 'dereferencing type-puned ...' warnings enum { STATUS_LAST = 0, @@ -137,8 +138,8 @@ predictor_state * predictor_decoder_init (predictor_state *state, int predictor, state->pixbufsize = (int)(compbuf > pixbuf ? compbuf : pixbuf); buffersize = rowsize * sizeof(uint8_t); buffer = (uint8_t *)util_calloc(buffersize, 1); - if (state->pixbufsize > sizeof(state->compbuffer)) // components > MAX_COMPONENTS - state->prevcomp = (predictor_component_t *)util_calloc(state->pixbufsize, 1); + if ((size_t)state->pixbufsize > sizeof(state->compbuffer)) // components > MAX_COMPONENTS + state->prevcomp = (predictor_component_t *)util_calloc(state->pixbufsize, 1); else state->prevcomp = state->compbuffer; // &state->prevcomp == &state->prevpixel @@ -251,17 +252,22 @@ static int read_scanline (predictor_state *state, iof *I, int size) #define up_pixel_byte(state) (state->rowup[state->rowindex]) #define upleft_pixel_byte(state) (state->rowup[state->rowindex - state->pixelsize]) #define left_pixel_byte(state) (state->rowsave[state->rowindex - state->pixelsize]) -#define save_pixel_byte(state, c) (state->rowsave[state->rowindex] = c) +#define save_pixel_byte(state, c) (state->rowsave[state->rowindex] = (uint8_t)(c)) /* tiff predictor macros; on components */ #define left_pixel_component(state) (state->prevcomp[state->compindex]) // tiff predictor with 2, 4, 8, 16 components #define left_pixel_value(state) (state->prevpixel[0]) // tiff predictor with 1bit components + +/* assignment in conditional #define save_pixel_component(state, c) ((void)\ - ((state->prevcomp[state->compindex] = c), \ - (++state->compindex < state->components || (state->compindex = 0)))) + ((state->prevcomp[state->compindex] = (predictor_component_t)(c)), \ + ++state->compindex, (state->compindex < state->components || (state->compindex = 0)))) +*/ +#define save_pixel_component(state, c) \ + do { state->prevcomp[state->compindex] = (predictor_component_t)(c); if (++state->compindex >= state->components) state->compindex = 0; } while (0) -#define save_pixel_value(state, c) (state->prevpixel[0] = c) +#define save_pixel_value(state, c) (state->prevpixel[0] = (predictor_pixel1b_t)(c)) /* Once the codec function is done with the scanline, we set imaginary left pixel data to zero, and reset row counters to zero in order to allow buffering another input scanline. */ @@ -724,7 +730,7 @@ static size_t predictor_encoder (iof *F, iof_mode mode) { case IOFFLUSH: state->flush = 1; - // fall through + FALLTHRU // fall through case IOFWRITE: F->end = F->pos; F->pos = F->buf; @@ -745,25 +751,25 @@ static size_t predictor_encoder (iof *F, iof_mode mode) iof * iof_filter_predictor_decoder (iof *N, int predictor, int rowsamples, int components, int compbits) { iof *I; - predictor_state *state; - I = iof_filter_reader(predictor_decoder, sizeof(predictor_state), &state); + predictor_state_pointer P; + I = iof_filter_reader(predictor_decoder, sizeof(predictor_state), &P.voidstate); iof_setup_next(I, N); - if (predictor_decoder_init(state, predictor, rowsamples, components, compbits) == NULL) + if (predictor_decoder_init(P.predictorstate, predictor, rowsamples, components, compbits) == NULL) { iof_discard(I); return NULL; } - state->flush = 1; + P.predictorstate->flush = 1; return I; } iof * iof_filter_predictor_encoder (iof *N, int predictor, int rowsamples, int components, int compbits) { iof *O; - predictor_state *state; - O = iof_filter_writer(predictor_encoder, sizeof(predictor_state), &state); + predictor_state_pointer P; + O = iof_filter_writer(predictor_encoder, sizeof(predictor_state), &P.voidstate); iof_setup_next(O, N); - if (predictor_encoder_init(state, predictor, rowsamples, components, compbits) == NULL) + if (predictor_encoder_init(P.predictorstate, predictor, rowsamples, components, compbits) == NULL) { iof_discard(O); return NULL; diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilfpred.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilfpred.h index 6ae2f893586..6ae2f893586 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilfpred.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilfpred.h diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utiliof.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utiliof.c index 2a1c6c7eeb8..a7141bfb682 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utiliof.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utiliof.c @@ -1,4 +1,4 @@ -/* input/iutput stream */ +/* input/output stream */ #include <stdlib.h> #include <string.h> @@ -8,8 +8,6 @@ #include "utillog.h" #include "utiliof.h" -#include "utilarm.h" - /* commons */ void * iof_copy_data (const void *data, size_t size) @@ -127,7 +125,7 @@ iof_file * iof_file_rdata_init (iof_file *iofile, const void *data, size_t size) iofile->rbuf = iofile->rpos = (const uint8_t *)data; iofile->rend = iofile->rbuf + size; iofile->offset = NULL; - iofile->size = 0; // letse keep it consequently set to zero (only for user disposal) + iofile->size = 0; // lets keep it consequently set to zero (only for user disposition) iofile->name = NULL; iofile->refcount = 0; iofile->flags = IOF_FILE_DEFAULTS|IOF_DATA; @@ -155,7 +153,7 @@ iof_file * iof_file_reader_from_file_handle (iof_file *iofile, const char *filen { if ((data = iof_copy_file_handle_data(file, &size)) == NULL) { - if (closefile) + if (closefile) // callers expect close also on failure fclose(file); return NULL; } @@ -186,7 +184,7 @@ iof_file * iof_file_reader_from_file (iof_file *iofile, const char *filename, in FILE *file; if ((file = fopen(filename, "rb")) == NULL) return NULL; - return iof_file_reader_from_file_handle(iofile, filename, file, preload, 1); + return iof_file_reader_from_file_handle(iofile, filename, file, preload, 1); // takes care to fclose() on failure } iof_file * iof_file_reader_from_data (iof_file *iofile, const void *data, size_t size, int preload, int freedata) @@ -234,15 +232,15 @@ iof_file * iof_file_writer_from_file (iof_file *iofile, const char *filename) */ /* -Because of limited number of FILE* handles available, we may need to close contained handle -between accessing it. In applications so far (fonts, images) we typically need the source -to parse the file on creation and to rewrite or reload the data on dump. All iof_file api -functions assume that iofile has FILE* opened. Reopening it on every access (ftell, fseek, -read/write) makes no sense, as we would effectively loose control. If the caller invalidates -iofile by closing and nulling its file handle, it is also responsible to reopen when necessary. +Because of limited number of FILE* handles available, we may need to close/reopen a file handle +when accessing it. In applications so far (fonts, images) we typically need the entire source +to parse the file on object creation and to rewrite or reload the data on dump. All iof_file API +functions assume that iofile has FILE* opened. Reopening it on every access (ftell, fseek, read/write) +makes no sense. So if the caller invalidates iofile by closing and NULLing its file handle, +it is also responsible to reopen when necessary. */ -int iof_file_close_input (iof_file *iofile) +int iof_file_reclose_input (iof_file *iofile) { FILE *file; if (iofile->flags & IOF_DATA) @@ -292,7 +290,7 @@ void iof_file_free (iof_file *iofile) else if ((file = iof_file_get_fh(iofile)) != NULL) { if (iofile->flags & IOF_CLOSE_FILE) - fclose(file); + fclose(file); iof_file_set_fh(iofile, NULL); } iof_file_set_name(iofile, NULL); @@ -300,6 +298,42 @@ void iof_file_free (iof_file *iofile) util_free(iofile); } +/* +An attempt to close iofile input keeping things safe. In bindings we sometimes we need to force +closing the file handle, otherwise it is closed when garbage collector graciously calls destroyer. +Eg. we are done with an object representing pdf/image/font, but we can't move/replace it, as the +host language keeps the garbage that keeps a file handle. When we call fclose(), we also have to +set the handle to NULL. In many places we assume, that if the iofile wraps FILE *, than the handle +is operable (no NULL checks). To close the handle keeping iofile alive safe, we can silently convert +it dummy IOF_DATA buffer. +*/ + +void iof_file_close_input (iof_file *iofile) +{ + FILE *file; + if (iofile->flags & IOF_DATA) + { + if (iofile->flags & IOF_BUFFER_ALLOC) + { + iofile->flags &= ~IOF_BUFFER_ALLOC; + if (iofile->buf != NULL) + { + util_free(iofile->buf); + //iofile->buf = iofile->pos = iofile->end = NULL; + } + } + } + else if ((file = iof_file_get_fh(iofile)) != NULL) + { + iof_file_set_fh(iofile, NULL); + fclose(file); + } + iof_file_set_name(iofile, NULL); + /* now make it a dummy string iofile */ + iofile->buf = iofile->pos = iofile->end = NULL; + iofile->flags |= IOF_DATA; +} + /* set filename for reopen */ void iof_file_set_name (iof_file *iofile, const char *name) @@ -355,7 +389,7 @@ long iof_file_tell (iof_file *iofile) } size_t iof_file_size (iof_file *iofile) -{ +{ long pos, size; FILE *file; if (iofile->flags & IOF_DATA) @@ -427,7 +461,7 @@ size_t iof_file_write (const void *ptr, size_t size, size_t items, iof_file *iof size_t space, sizesofar, bytes; bytes = size * items; if (bytes > (size_t)iof_left(iofile)) - { + { if ((space = iof_space(iofile)) == 0) // allow iofile->buf/end initially NULL space = BUFSIZ; for (sizesofar = iof_size(iofile), space <<= 1; sizesofar + bytes > space; space <<= 1) @@ -449,13 +483,13 @@ size_t iof_file_ensure (iof_file *iofile, size_t bytes) size_t space, sizesofar, left; left = (size_t)iof_left(iofile); if (bytes > left) - { + { if ((space = iof_space(iofile)) == 0) // allow iofile->buf/end initially NULL space = BUFSIZ; for (sizesofar = iof_size(iofile), space <<= 1; sizesofar + bytes > space; space <<= 1); return iof_file_data_resizeto(iofile, space); } - return left; + return left; } return 0; } @@ -802,10 +836,7 @@ static size_t file_reader (iof *I, iof_mode mode) iof * iof_setup_file_handle_reader (iof *I, void *buffer, size_t space, FILE *f) { - if (I == NULL) - iof_setup_reader(I, buffer, space); - else - iof_reader_buffer(I, buffer, space); + iof_setup_reader(I, buffer, space); iof_setup_file(I, f); I->more = file_reader; return I; @@ -816,10 +847,7 @@ iof * iof_setup_file_reader (iof *I, void *buffer, size_t space, const char *fil FILE *f; if ((f = fopen(filename, "rb")) == NULL) return NULL; - if (I == NULL) - iof_setup_reader(I, buffer, space); - else - iof_reader_buffer(I, buffer, space); + iof_setup_reader(I, buffer, space); iof_setup_file(I, f); I->flags |= IOF_CLOSE_FILE; I->more = file_reader; @@ -849,10 +877,7 @@ static size_t file_writer (iof *O, iof_mode mode) iof * iof_setup_file_handle_writer (iof *O, void *buffer, size_t space, FILE *f) { - if (O == NULL) - iof_setup_writer(O, buffer, space); - else - iof_writer_buffer(O, buffer, space); + iof_setup_writer(O, buffer, space); iof_setup_file(O, f); O->more = file_writer; return O; @@ -863,10 +888,7 @@ iof * iof_setup_file_writer (iof *O, void *buffer, size_t space, const char *fil FILE *f; if ((f = fopen(filename, "wb")) == NULL) return NULL; - if (O == NULL) - iof_setup_writer(O, buffer, space); - else - iof_writer_buffer(O, buffer, space); + iof_setup_writer(O, buffer, space); iof_setup_file(O, f); O->flags |= IOF_CLOSE_FILE; O->more = file_writer; @@ -996,10 +1018,7 @@ static size_t iof_mem_handler (iof *O, iof_mode mode) iof * iof_setup_buffer (iof *O, void *buffer, size_t space) { - if (O == NULL) - iof_setup_writer(O, buffer, space); - else - iof_writer_buffer(O, buffer, space); + iof_setup_writer(O, buffer, space); O->link = NULL; O->flags |= IOF_DATA; O->more = iof_mem_handler; @@ -1008,7 +1027,8 @@ iof * iof_setup_buffer (iof *O, void *buffer, size_t space) iof * iof_setup_buffermin (iof *O, void *buffer, size_t space, size_t min) { - if ((O = iof_setup_buffer(O, buffer, space)) != NULL && space < min) // just allocate min now to avoid further rewriting + iof_setup_buffer(O, buffer, space); + if (space < min) // allocate min to avoid further rewriting { O->buf = O->pos = (uint8_t *)util_malloc(min); O->flags |= IOF_BUFFER_ALLOC; @@ -1020,11 +1040,11 @@ iof * iof_setup_buffermin (iof *O, void *buffer, size_t space, size_t min) iof * iof_buffer_create (size_t space) { uint8_t *buffer; - iof *O; - space += sizeof(iof); - buffer = util_malloc(space); - if ((O = iof_setup_buffer(NULL, buffer, space)) != NULL) - O->flags |= IOF_ALLOC; + iof *O; + O = (iof *)util_malloc(space); + buffer = (uint8_t *)(O + 1); + iof_setup_buffer(O, buffer, space); + O->flags |= IOF_ALLOC; return O; } @@ -1098,7 +1118,7 @@ size_t iof_read (iof *I, void *to, size_t size) { size_t leftin, done = 0; char *s = (char *)to; - + if ((leftin = iof_left(I)) == 0) if ((leftin = iof_input(I)) == 0) return done; @@ -1131,7 +1151,7 @@ size_t iof_write_file_handle (iof *O, FILE *file) return 0; size = 0; do { - readout = fread(O->pos, 1, leftout, file); + readout = fread(O->pos, 1, leftout, file); O->pos += readout; size += readout; } while(readout == leftout && (leftout = iof_output(O)) > 0); @@ -1159,7 +1179,7 @@ size_t iof_write_iofile (iof *O, iof_file *iofile, int savepos) file = iof_file_get_fh(iofile); if (savepos) { - offset = ftell(file); + offset = ftell(file); size = iof_write_file_handle(O, file); fseek(file, offset, SEEK_SET); return size; @@ -1289,7 +1309,7 @@ int iof_get_int32 (iof *I, int32_t *number) return 1; } -int iof_get_intlw (iof *I, intlw_t *number) +int iof_get_slong (iof *I, long *number) { int sign, c = iof_char(I); iof_scan_sign(I, c, sign); @@ -1317,7 +1337,15 @@ int iof_get_uint32 (iof *I, uint32_t *number) return 1; } -int iof_get_uintlw (iof *I, uintlw_t *number) +int iof_get_ulong (iof *I, unsigned long *number) +{ + int c = iof_char(I); + if (!base10_digit(c)) return 0; + iof_read_integer(I, c, *number); + return 1; +} + +int iof_get_usize (iof *I, size_t *number) { int c = iof_char(I); if (!base10_digit(c)) return 0; @@ -1344,7 +1372,7 @@ int iof_get_int32_radix (iof *I, int32_t *number, int radix) } -int iof_get_intlw_radix (iof *I, intlw_t *number, int radix) +int iof_get_slong_radix (iof *I, long *number, int radix) { int sign, c = iof_char(I); iof_scan_sign(I, c, sign); @@ -1372,7 +1400,15 @@ int iof_get_uint32_radix (iof *I, uint32_t *number, int radix) return 1; } -int iof_get_uintlw_radix (iof *I, uintlw_t *number, int radix) +int iof_get_ulong_radix (iof *I, unsigned long *number, int radix) +{ + int c = iof_char(I); + if (!base10_digit(c)) return 0; + iof_read_radix(I, c, *number, radix); + return 1; +} + +int iof_get_usize_radix (iof *I, size_t *number, int radix) { int c = iof_char(I); if (!base10_digit(c)) return 0; @@ -1505,7 +1541,7 @@ int iof_get_double (iof *I, double *number) // cf. string_to_double() return 1; } -int iof_get_float (iof *I, float *number) // cf. string_to_float() in utilnumber.c +int iof_get_float (iof *I, float *number) // cf. string_to_float() { int sign, exponent10, c = iof_char(I); iof_scan_sign(I, c, sign); @@ -1527,7 +1563,7 @@ int iof_get_float (iof *I, float *number) // cf. string_to_float() in utilnumber return 1; } -int iof_conv_double (iof *I, double *number) // cf. convert_to_double() in utilnumber.c +int iof_conv_double (iof *I, double *number) // cf. convert_to_double() { int sign, exponent10, c = iof_char(I); iof_scan_sign(I, c, sign); @@ -1561,138 +1597,144 @@ int iof_conv_float (iof *I, float *number) // cf. convert_to_float() /* integer to iof; return a number of written bytes */ -#define iof_copy_number_buffer(O, s, p) for (p = s; *p && iof_writable(O); iof_set(O, *p), ++p) - size_t iof_put_int32 (iof *O, int32_t number) { - const char *s, *p; - s = int32_to_string(number); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = int32_to_string(number, &size); + return iof_write(O, s, size); } -size_t iof_put_intlw (iof *O, intlw_t number) +size_t iof_put_slong (iof *O, long number) { - const char *s, *p; - s = intlw_to_string(number); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = slong_to_string(number, &size); + return iof_write(O, s, size); } size_t iof_put_int64 (iof *O, int64_t number) { - const char *s, *p; - s = int64_to_string(number); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = int64_to_string(number, &size); + return iof_write(O, s, size); } size_t iof_put_uint32 (iof *O, uint32_t number) { - const char *s, *p; - s = uint32_to_string(number); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = uint32_to_string(number, &size); + return iof_write(O, s, size); } -size_t iof_put_uintlw (iof *O, uintlw_t number) +size_t iof_put_ulong (iof *O, unsigned long number) { - const char *s, *p; - s = uintlw_to_string(number); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = ulong_to_string(number, &size); + return iof_write(O, s, size); } -size_t iof_put_uint64 (iof *O, uint64_t number) +size_t iof_put_usize (iof *O, size_t number) { - const char *s, *p; - s = uint64_to_string(number); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = usize_to_string(number, &size); + return iof_write(O, s, size); } -size_t iof_put_int32_radix (iof *O, int32_t number, int radix) +size_t iof_put_uint64 (iof *O, uint64_t number) { - const char *s, *p; - s = int32_to_radix(number, radix); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = uint64_to_string(number, &size); + return iof_write(O, s, size); } -size_t iof_put_intlw_radix (iof *O, intlw_t number, int radix) +size_t iof_put_int32_radix (iof *O, int32_t number, int radix, int uc) { - const char *s, *p; - s = intlw_to_radix(number, radix); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = int32_to_radix(number, radix, uc, &size); + return iof_write(O, s, size); } -size_t iof_put_int64_radix (iof *O, int64_t number, int radix) +size_t iof_put_slong_radix (iof *O, long number, int radix, int uc) { - const char *s, *p; - s = int64_to_radix(number, radix); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = slong_to_radix(number, radix, uc, &size); + return iof_write(O, s, size); } -size_t iof_put_uint32_radix (iof *O, uint32_t number, int radix) +size_t iof_put_int64_radix (iof *O, int64_t number, int radix, int uc) { - const char *s, *p; - s = uint32_to_radix(number, radix); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = int64_to_radix(number, radix, uc, &size); + return iof_write(O, s, size); } -size_t iof_put_uintlw_radix (iof *O, uintlw_t number, int radix) +size_t iof_put_uint32_radix (iof *O, uint32_t number, int radix, int uc) { - const char *s, *p; - s = uintlw_to_radix(number, radix); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = uint32_to_radix(number, radix, uc, &size); + return iof_write(O, s, size); } -size_t iof_put_uint64_radix (iof *O, uint64_t number, int radix) +size_t iof_put_ulong_radix (iof *O, unsigned long number, int radix, int uc) { - const char *s, *p; - s = uint64_to_radix(number, radix); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = ulong_to_radix(number, radix, uc, &size); + return iof_write(O, s, size); } -/* roman numerals */ +size_t iof_put_usize_radix (iof *O, size_t number, int radix, int uc) +{ + const char *s; + size_t size; + s = usize_to_radix(number, radix, uc, &size); + return iof_write(O, s, size); +} -size_t iof_put_roman_uc (iof *O, uint16_t number) +size_t iof_put_uint64_radix (iof *O, uint64_t number, int radix, int uc) { - const char *s, *p; - s = uint16_to_roman_uc(number); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = uint64_to_radix(number, radix, uc, &size); + return iof_write(O, s, size); } -size_t iof_put_roman_lc (iof *O, uint16_t number) +/* roman numerals */ + +size_t iof_put_roman (iof *O, uint16_t number, int uc) { - const char *s, *p; - s = uint16_to_roman_lc(number); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = uint16_to_roman(number, uc, &size); + return iof_write(O, s, size); } /* double/float to iof; return the number of written bytes */ size_t iof_put_double (iof *O, double number, int digits) { - const char *s, *p; - s = double_to_string(number, digits); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = double_to_string(number, digits, &size); + return iof_write(O, s, size); } size_t iof_put_float (iof *O, float number, int digits) { - const char *s, *p; - s = float_to_string(number, digits); - iof_copy_number_buffer(O, s, p); - return p - s; + const char *s; + size_t size; + s = float_to_string(number, digits, &size); + return iof_write(O, s, size); } /* iof to binary integer; pretty common */ @@ -1778,7 +1820,7 @@ uint8_t * iof_file_reader_data (iof_file *iofile, size_t *size) { uint8_t *data; if (!(iofile->flags & IOF_DATA) || iofile->pos == NULL || (*size = (size_t)iof_left(iofile)) == 0) - return NULL; + return NULL; if (iofile->flags & IOF_BUFFER_ALLOC) { data = iofile->buf; // iofile->pos; // returned must be freeable, makes sense when ->buf == ->pos @@ -1795,7 +1837,7 @@ uint8_t * iof_file_writer_data (iof_file *iofile, size_t *size) { uint8_t *data; if (!(iofile->flags & IOF_DATA) || iofile->buf == NULL || (*size = (size_t)iof_size(iofile)) == 0) - return NULL; + return NULL; if (iofile->flags & IOF_BUFFER_ALLOC) { iofile->flags &= ~IOF_BUFFER_ALLOC; @@ -1886,7 +1928,7 @@ size_t iof_result_to_file_handle (iof *F, FILE *file) const void *data; size_t size; data = iof_result(F, size); - return iof_data_to_file_handle(data, size, file); + return iof_data_to_file_handle(data, size, file); } size_t iof_result_to_file (iof *F, const char *filename) @@ -1935,16 +1977,25 @@ size of img: 496 typedef struct iof_heap iof_heap; +typedef struct { + iof_heap *heap; +} iof_heap_ghost; + + struct iof_heap { - uint8_t *data, *pos; + union { uint8_t *data; iof_heap_ghost *gdata; }; // union instead of casts (ARM) + union { uint8_t *pos; iof_heap_ghost *gpos; }; size_t size, space; iof_heap *next, *prev; int refcount; + uint8_t dummy[4]; // pad to 8N bytes }; -typedef struct { - iof_heap *heap; -} iof_heap_ghost; +/* +We use hidden heap pointer for every allocated buffer, so heap->data should be kept properly aligned. +Dummy 4-bytes pad doesn't really matter (the pad is there anyway), but iof_heap_take() must pad the +requested size. +*/ static iof_heap * iof_buffers_heap = NULL; static iof_heap * iof_filters_heap = NULL; @@ -1960,7 +2011,7 @@ static iof_heap * iof_heap_new (size_t space) { iof_heap *iofheap; iofheap = (iof_heap *)util_malloc(sizeof(iof_heap) + space); - iofheap->data = iofheap->pos = (uint8_t *)(iofheap + 1); + iofheap->gdata = iofheap->gpos = (iof_heap_ghost *)(iofheap + 1); iofheap->size = iofheap->space = space; iofheap->next = NULL; iofheap->prev = NULL; @@ -2003,25 +2054,8 @@ void iof_filters_free (void) iof_filters_heap = NULL; } -#if ARM_COMPLIANT -#define iof_heap_get(hp, ghost, data, siz) \ - (ghost = (iof_heap_ghost *)((void*)((hp)->pos)), \ - ghost->heap = hp, \ - data = (uint8_t *)(ghost + 1), \ - (hp)->pos += siz, \ - (hp)->size -= siz, \ - ++(hp)->refcount) -#else #define iof_heap_get(hp, ghost, data, siz) \ - (ghost = (iof_heap_ghost *)((hp)->pos), \ - ghost->heap = hp, \ - data = (uint8_t *)(ghost + 1), \ - (hp)->pos += siz, \ - (hp)->size -= siz, \ - ++(hp)->refcount) - -#endif - + (ghost = (hp)->gpos, ghost->heap = (hp), data = (uint8_t *)(ghost + 1), (hp)->pos += siz, (hp)->size -= siz, ++(hp)->refcount) static void * iof_heap_take (iof_heap **pheap, size_t size) { @@ -2030,13 +2064,15 @@ static void * iof_heap_take (iof_heap **pheap, size_t size) iof_heap *heap, *newheap, *next; heap = *pheap; + if (size & 7) + size += 8 - (size & 7); // pad to 8N bytes so that (heap->pos + size) remains properly aligned size += sizeof(iof_heap_ghost); if (heap->size >= size) { /* take cheap mem from main heap */ iof_heap_get(heap, ghost, data, size); return data; } - if (size <= heap->space >> 1) + if (size <= (heap->space >> 1)) { /* make new cheap heap, make it front */ *pheap = newheap = iof_heap_new(heap->space); newheap->next = heap; @@ -2058,7 +2094,7 @@ static void * iof_heap_take (iof_heap **pheap, size_t size) return data; } -void iof_heap_back (void *data) +static void iof_heap_back (void *data) { iof_heap_ghost *ghost; iof_heap *heap, *next, *prev; @@ -2085,21 +2121,17 @@ void iof_heap_back (void *data) } } +/**/ + +/* void * iof_filter_new (size_t size) -{ // to be removed +{ void *data; - iof_filters_init(); data = iof_heap_take(&iof_filters_heap, size); return memset(data, 0, size); } - -static uint8_t * iof_filter_buffer_new (size_t *psize) -{ - iof_filters_init(); - *psize = IOF_BUFFER_SIZE; - return iof_heap_take(&iof_buffers_heap, IOF_BUFFER_SIZE); -} +*/ iof * iof_filter_reader_new (iof_handler handler, size_t statesize, void **pstate) { @@ -2111,8 +2143,9 @@ iof * iof_filter_reader_new (iof_handler handler, size_t statesize, void **pstat iof_filters_init(); filter = iof_heap_take(&iof_filters_heap, sizeof(iof) + statesize); F = (iof *)memset(filter, 0, sizeof(iof) + statesize); - buffer = iof_filter_buffer_new(&buffersize); - iof_reader_buffer(F, buffer, buffersize); + buffer = iof_heap_take(&iof_buffers_heap, IOF_BUFFER_SIZE); + buffersize = IOF_BUFFER_SIZE; + iof_setup_reader(F, buffer, buffersize); F->flags |= IOF_HEAP|IOF_BUFFER_HEAP; F->more = handler; *pstate = (F + 1); @@ -2123,10 +2156,11 @@ iof * iof_filter_reader_with_buffer_new (iof_handler handler, size_t statesize, { // for filters that has own buffer (string, some image filters) iof *F; void *filter; + iof_filters_init(); filter = iof_heap_take(&iof_filters_heap, sizeof(iof) + statesize); F = (iof *)memset(filter, 0, sizeof(iof) + statesize); - iof_reader_buffer(F, buffer, buffersize); + iof_setup_reader(F, buffer, buffersize); F->flags |= IOF_HEAP; F->more = handler; *pstate = (F + 1); @@ -2143,31 +2177,35 @@ iof * iof_filter_writer_new (iof_handler handler, size_t statesize, void **pstat iof_filters_init(); filter = iof_heap_take(&iof_filters_heap, sizeof(iof) + statesize); F = (iof *)memset(filter, 0, sizeof(iof) + statesize); - buffer = iof_filter_buffer_new(&buffersize); - iof_writer_buffer(F, buffer, buffersize); + buffer = iof_heap_take(&iof_buffers_heap, IOF_BUFFER_SIZE); + buffersize = IOF_BUFFER_SIZE; + iof_setup_writer(F, buffer, buffersize); F->flags |= IOF_HEAP|IOF_BUFFER_HEAP; F->more = handler; *pstate = (F + 1); return F; } -iof * iof_filter_writer_with_buffer_new (iof_handler handler, size_t statesize, void **pstate, void *buffer, size_t size) +iof * iof_filter_writer_with_buffer_new (iof_handler handler, size_t statesize, void **pstate, void *buffer, size_t buffersize) { iof *F; void *filter; - size_t buffersize; iof_filters_init(); filter = iof_heap_take(&iof_filters_heap, sizeof(iof) + statesize); F = (iof *)memset(filter, 0, sizeof(iof) + statesize); - buffer = iof_filter_buffer_new(&buffersize); - iof_writer_buffer(F, buffer, buffersize); + iof_setup_writer(F, buffer, buffersize); F->flags |= IOF_HEAP; F->more = handler; *pstate = (F + 1); return F; } +/**/ + +#define iof_filter_free(F) iof_heap_back(F) +#define iof_filter_buffer_free(data) iof_heap_back(data) + /* close */ #define iof_close_next(F) ((void)(iof_decref((F)->next), (F)->next = NULL, 0)) @@ -2236,8 +2274,8 @@ void iof_discard (iof *F) iof_close_file(F); else if (F->flags & IOF_FILE) iof_close_iofile(F); - else if (F->flags & IOF_NEXT) - iof_close_next(F); + //else if (F->flags & IOF_NEXT) + // iof_close_next(F); iof_close_buffer(F); if (F->flags & IOF_HEAP) iof_filter_free(F); @@ -2287,6 +2325,7 @@ size_t iof_decoder_retval (iof *I, const char *type, iof_status status) return 0; case IOFEOF: // this is the last chunk, I->flags |= IOF_STOPPED; // so stop it and fall + FALLTHRU // fall through case IOFFULL: // prepare pointers to read from I->buf I->end = I->pos; I->pos = I->buf; @@ -2322,7 +2361,6 @@ typedef struct { size_t offset; } file_state; - #define file_state_init(state, off, len) ((state)->offset = off, (state)->length = len) typedef struct { @@ -2332,6 +2370,12 @@ typedef struct { #define stream_state_init(state, off, len) ((state)->offset = off, (state)->length = len) +/* union type to avoid 'dereferencing type-punned .. ' warnings on (void **) case */ + +typedef union { file_state *filestate; stream_state *streamstate; void *voidstate; } fs_state_pointer; + +/**/ + static size_t file_read (iof *I) { size_t bytes, tail; @@ -2505,24 +2549,24 @@ static size_t filter_iofile_writer (iof *O, iof_mode mode) iof * iof_filter_file_handle_reader (FILE *file) { iof *I; - file_state *state; + fs_state_pointer P; if (file == NULL) return NULL; - I = iof_filter_reader(filter_file_reader, sizeof(file_state), &state); + I = iof_filter_reader(filter_file_reader, sizeof(file_state), &P.voidstate); iof_setup_file(I, file); - file_state_init(state, 0, 0); + file_state_init(P.filestate, 0, 0); return I; } iof * iof_filter_file_handle_writer (FILE *file) { iof *O; - file_state *state; + fs_state_pointer P; if (file == NULL) return NULL; - O = iof_filter_writer(filter_file_writer, sizeof(file_state), &state); + O = iof_filter_writer(filter_file_writer, sizeof(file_state), &P.voidstate); iof_setup_file(O, file); - file_state_init(state, 0, 0); + file_state_init(P.filestate, 0, 0); return O; } @@ -2531,22 +2575,22 @@ iof * iof_filter_file_handle_writer (FILE *file) iof * iof_filter_iofile_reader (iof_file *iofile, size_t offset) { iof *I; - file_state *state; + fs_state_pointer P; if (!iof_file_reopen(iofile)) return NULL; - I = iof_filter_reader(filter_iofile_reader, sizeof(file_state), &state); + I = iof_filter_reader(filter_iofile_reader, sizeof(file_state), &P.voidstate); iof_setup_iofile(I, iofile); - file_state_init(state, offset, 0); + file_state_init(P.filestate, offset, 0); return I; } iof * iof_filter_iofile_writer (iof_file *iofile, size_t offset) { iof *O; - file_state *state; - O = iof_filter_writer(filter_iofile_writer, sizeof(file_state), &state); + fs_state_pointer P; + O = iof_filter_writer(filter_iofile_writer, sizeof(file_state), &P.voidstate); iof_setup_iofile(O, iofile); - file_state_init(state, offset, 0); + file_state_init(P.filestate, offset, 0); return O; } @@ -2555,13 +2599,13 @@ iof * iof_filter_iofile_writer (iof_file *iofile, size_t offset) iof * iof_filter_file_reader (const char *filename) { iof *I; - file_state *state; + fs_state_pointer P; FILE *file; if ((file = fopen(filename, "rb")) == NULL) return NULL; - I = iof_filter_reader(filter_file_reader, sizeof(file_state), &state); + I = iof_filter_reader(filter_file_reader, sizeof(file_state), &P.voidstate); iof_setup_file(I, file); - file_state_init(state, 0, 0); + file_state_init(P.filestate, 0, 0); I->flags |= IOF_CLOSE_FILE; return I; } @@ -2569,13 +2613,13 @@ iof * iof_filter_file_reader (const char *filename) iof * iof_filter_file_writer (const char *filename) { iof *O; - file_state *state; + fs_state_pointer P; FILE *file; if ((file = fopen(filename, "wb")) == NULL) return NULL; - O = iof_filter_writer(filter_file_writer, sizeof(file_state), &state); + O = iof_filter_writer(filter_file_writer, sizeof(file_state), &P.voidstate); iof_setup_file(O, file); - file_state_init(state, 0, 0); + file_state_init(P.filestate, 0, 0); O->flags |= IOF_CLOSE_FILE; return O; } @@ -2617,18 +2661,18 @@ iof * iof_filter_string_writer (const void *s, size_t length) } iof * iof_filter_buffer_writer (size_t size) -{ // filter alternative of iof_buffer_create() +{ // cmp iof_buffer_create() iof *O; - void *dummy; + fs_state_pointer dummy; uint8_t *buffer; if (size > IOF_BUFFER_SIZE) { buffer = (uint8_t *)util_malloc(size); - O = iof_filter_writer_with_buffer(iof_mem_handler, 0, &dummy, buffer, size); + O = iof_filter_writer_with_buffer(iof_mem_handler, 0, &dummy.voidstate, buffer, size); O->flags |= IOF_BUFFER_ALLOC; return O; } - return iof_filter_writer(iof_mem_handler, 0, &dummy); + return iof_filter_writer(iof_mem_handler, 0, &dummy.voidstate); } /* stream */ @@ -2754,10 +2798,10 @@ static size_t filter_iofile_stream_reader (iof *I, iof_mode mode) iof * iof_filter_stream_reader (FILE *file, size_t offset, size_t length) { iof *I; - stream_state *state; - I = iof_filter_reader(filter_file_stream_reader, sizeof(stream_state), &state); + fs_state_pointer P; + I = iof_filter_reader(filter_file_stream_reader, sizeof(stream_state), &P.voidstate); iof_setup_file(I, file); - stream_state_init(state, offset, length); + stream_state_init(P.streamstate, offset, length); fseek(file, (long)offset, SEEK_SET); // or perhaps it should be call in file_stream_read(), like iof_file_sync()? return I; } @@ -2765,12 +2809,12 @@ iof * iof_filter_stream_reader (FILE *file, size_t offset, size_t length) iof * iof_filter_stream_coreader (iof_file *iofile, size_t offset, size_t length) { iof *I; - stream_state *state; + fs_state_pointer P; if (!iof_file_reopen(iofile)) return NULL; - I = iof_filter_reader(filter_iofile_stream_reader, sizeof(stream_state), &state); + I = iof_filter_reader(filter_iofile_stream_reader, sizeof(stream_state), &P.voidstate); iof_setup_iofile(I, iofile); - stream_state_init(state, offset, length); + stream_state_init(P.streamstate, offset, length); return I; } @@ -2855,20 +2899,20 @@ static size_t filter_iofile_stream_writer (iof *O, iof_mode mode) iof * iof_filter_stream_writer (FILE *file) { iof *O; - stream_state *state; - O = iof_filter_writer(filter_file_stream_writer, sizeof(stream_state), &state); + fs_state_pointer P; + O = iof_filter_writer(filter_file_stream_writer, sizeof(stream_state), &P.voidstate); iof_setup_file(O, file); - stream_state_init(state, 0, 0); + stream_state_init(P.streamstate, 0, 0); return O; } iof * iof_filter_stream_cowriter (iof_file *iofile, size_t offset) { iof *O; - stream_state *state; - O = iof_filter_writer(filter_iofile_stream_writer, sizeof(stream_state), &state); + fs_state_pointer P; + O = iof_filter_writer(filter_iofile_stream_writer, sizeof(stream_state), &P.voidstate); iof_setup_iofile(O, iofile); - stream_state_init(state, offset, 0); + stream_state_init(P.streamstate, offset, 0); return O; } @@ -2876,20 +2920,19 @@ iof * iof_filter_stream_cowriter (iof_file *iofile, size_t offset) FILE * iof_filter_file_reader_source (iof *I, size_t *poffset, size_t *plength) { - stream_state *sstate; - file_state *fstate; + fs_state_pointer P; if (I->more == filter_file_stream_reader) // I is the result of iof_filter_stream_reader() { - sstate = iof_filter_state(stream_state *, I); - *poffset = sstate->offset; - *plength = sstate->length; // might be 0 but it is ok for file readers + P.streamstate = iof_filter_state(stream_state *, I); + *poffset = P.streamstate->offset; + *plength = P.streamstate->length; // might be 0 but it is ok for file readers return I->file; } if (I->more == filter_file_reader) { - fstate = iof_filter_state(file_state *, I); - *poffset = fstate->offset; - *plength = fstate->length; // might be 0 but it is ok for file readers + P.filestate = iof_filter_state(file_state *, I); + *poffset = P.filestate->offset; + *plength = P.filestate->length; // might be 0 but it is ok for file readers return I->file; } return NULL; @@ -2897,20 +2940,19 @@ FILE * iof_filter_file_reader_source (iof *I, size_t *poffset, size_t *plength) iof_file * iof_filter_file_coreader_source (iof *I, size_t *poffset, size_t *plength) { - stream_state *sstate; - file_state *fstate; + fs_state_pointer P; if (I->more == filter_iofile_stream_reader) // I is the result of iof_filter_stream_coreader() { - sstate = iof_filter_state(stream_state *, I); - *poffset = sstate->offset; - *plength = sstate->length; + P.streamstate = iof_filter_state(stream_state *, I); + *poffset = P.streamstate->offset; + *plength = P.streamstate->length; return I->iofile; } if (I->more == filter_iofile_reader) { - fstate = iof_filter_state(file_state *, I); - *poffset = fstate->offset; - *plength = fstate->length; + P.filestate = iof_filter_state(file_state *, I); + *poffset = P.filestate->offset; + *plength = P.filestate->length; return I->iofile; } return NULL; @@ -2921,7 +2963,7 @@ iof * iof_filter_reader_replacement (iof *P, iof_handler handler, size_t statesi iof *F; F = iof_filter_reader_with_buffer(handler, statesize, pstate, P->buf, P->space); F->flags |= IOF_BUFFER_HEAP; - //iof_reader_buffer(P, NULL, 0); + //iof_setup_reader(P, NULL, 0); //P->flags &= ~IOF_BUFFER_HEAP; iof_filter_free(P); return F; diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utiliof.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utiliof.h index 853a9ae523f..afd9c55ed88 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utiliof.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utiliof.h @@ -37,8 +37,8 @@ typedef struct iof_file { union { FILE *iofh; // access via iof_file_get_fh / iof_file_set_fh (below) union { - struct { uint8_t *buf, *pos, *end; }; - struct { const uint8_t *rbuf, *rpos, *rend; }; // to trick compiler warnings about cast discarding const + struct { uint8_t *buf, *pos, *end; }; + struct { const uint8_t *rbuf, *rpos, *rend; }; // to trick compiler warnings about cast discarding const }; }; size_t *offset; @@ -53,7 +53,7 @@ typedef struct iof_file { typedef struct iof iof; typedef size_t (*iof_handler) (iof *I, iof_mode mode); -/* iof structure */ +/* iof structure; keep 8N bytes */ #define IOF_MEMBERS \ union { \ @@ -152,21 +152,13 @@ is way larger the sizeof(iof) #define iof_decref(I) ((void)(--(I)->refcount <= 0 && iof_close(I))) #define iof_unref(I) (--(I)->refcount) -/* setting up iof and buffer from mem buffer of a given size */ - -#define iof_setup_reader(I, buffer, size) \ - ((I) = (iof *)(buffer), iof_reader_buffer(I, (I)+1, size - sizeof(iof))) - -#define iof_setup_writer(O, buffer, size) \ - ((O) = (iof *)buffer, iof_writer_buffer(O, (O)+1, size - sizeof(iof))) - /* binding buffer of a given size */ -#define iof_reader_buffer(I, buffer, size) \ +#define iof_setup_reader(I, buffer, size) \ ((I)->buf = (I)->pos = (I)->end = (uint8_t *)(buffer), \ (I)->space = size, (I)->flags = 0|IOF_READER, (I)->refcount = 0) -#define iof_writer_buffer(O, buffer, size) \ +#define iof_setup_writer(O, buffer, size) \ ((O)->buf = (O)->pos = (uint8_t *)(buffer), \ (O)->end = (uint8_t *)(buffer) + size, \ (O)->space = size, (O)->flags = 0|IOF_WRITER, (O)->refcount = 0) @@ -194,7 +186,7 @@ mode must be aware of some not yet read data, but treat it necessary only if IOF Parsers using iof input may protect not yet read data when there may be a need to put bytes back to the stream. This is trivial when I->pos > I->buf, as we can make a move by --I->pos. But when there is a need to put back more then one byte, we can protect the data tail, so that -realoder will rewrite it to the beginning of new data chunk. +realoder will rewrite it to the beginning of new data chunk. iof_tail(I) - internal, used by iof handlers at IOFREAD mode iof_protect_tail(I) - used by parsers to ensure some bytes chunk in one piece @@ -273,11 +265,13 @@ int iof_file_flush (iof_file *iofile); int iof_file_getc (iof_file *iofile); int iof_file_putc (iof_file *iofile, int c); -int iof_file_close_input (iof_file *iofile); +int iof_file_reclose_input (iof_file *iofile); int iof_file_reopen_input (iof_file *iofile); #define iof_file_reopen(iofile) (((iofile)->flags & IOF_REOPEN_FILE) ? iof_file_reopen_input(iofile) : 1) -#define iof_file_reclose(iofile) (void)(((iofile)->flags & IOF_RECLOSE_FILE) ? iof_file_close_input(iofile) : 0) +#define iof_file_reclose(iofile) (void)(((iofile)->flags & IOF_RECLOSE_FILE) ? iof_file_reclose_input(iofile) : 0) + +void iof_file_close_input (iof_file *iofile); /* wrappers of basic operations for iof */ @@ -303,25 +297,16 @@ size_t iof_fsize (iof *I); UTILAPI iof * iof_setup_file_handle_reader (iof *I, void *buffer, size_t space, FILE *f); UTILAPI iof * iof_setup_file_handle_writer (iof *O, void *buffer, size_t space, FILE *f); -#define iof_get_file_handle_reader(buffer, space, fh) iof_setup_file_handle_reader(NULL, buffer, space, fh) -#define iof_get_file_handle_writer(buffer, space, fh) iof_setup_file_handle_writer(NULL, buffer, space, fh) - /* file reader and writer */ UTILAPI iof * iof_setup_file_reader (iof *I, void *buffer, size_t space, const char *filename); UTILAPI iof * iof_setup_file_writer (iof *O, void *buffer, size_t space, const char *filename); -#define iof_get_file_reader(buffer, space, filename) iof_setup_file_reader(NULL, buffer, space, filename) -#define iof_get_file_writer(buffer, space, filename) iof_setup_file_writer(NULL, buffer, space, filename) - /* mem writer */ UTILAPI iof * iof_setup_buffer (iof *O, void *buffer, size_t space); UTILAPI iof * iof_setup_buffermin (iof *O, void *buffer, size_t space, size_t min); -#define iof_buffer(buffer, space) iof_setup_buffer(NULL, buffer, space) -#define iof_buffermin(buffer, space, min) iof_setup_buffermin(NULL, buffer, space, min) - UTILAPI iof * iof_buffer_create (size_t space); #define iof_buffer_new() iof_buffer_create(BUFSIZ) @@ -503,22 +488,36 @@ UTILAPI size_t iof_repc (iof *O, char c, size_t bytes); #define iof_scan_exponent10(I, c, exponent10) _scan_exponent10(c, exponent10, iof_next(I)) UTILAPI int iof_get_int32 (iof *I, int32_t *number); -UTILAPI int iof_get_intlw (iof *I, intlw_t *number); +UTILAPI int iof_get_slong (iof *I, long *number); UTILAPI int iof_get_int64 (iof *I, int64_t *number); UTILAPI int iof_get_uint32 (iof *I, uint32_t *number); -UTILAPI int iof_get_uintlw (iof *I, uintlw_t *number); +UTILAPI int iof_get_ulong (iof *I, unsigned long *number); +UTILAPI int iof_get_usize (iof *I, size_t *number); UTILAPI int iof_get_uint64 (iof *I, uint64_t *number); UTILAPI int iof_get_int32_radix (iof *I, int32_t *number, int radix); -UTILAPI int iof_get_intlw_radix (iof *I, intlw_t *number, int radix); +UTILAPI int iof_get_slong_radix (iof *I, long *number, int radix); UTILAPI int iof_get_int64_radix (iof *I, int64_t *number, int radix); UTILAPI int iof_get_uint32_radix (iof *I, uint32_t *number, int radix); -UTILAPI int iof_get_uintlw_radix (iof *I, uintlw_t *number, int radix); +UTILAPI int iof_get_ulong_radix (iof *I, unsigned long *number, int radix); +UTILAPI int iof_get_usize_radix (iof *I, size_t *number, int radix); UTILAPI int iof_get_uint64_radix (iof *I, uint64_t *number, int radix); -UTILAPI int iof_get_roman (iof *I, unsigned short int *number); +#if defined(INTLW_IS_INT64) +# define iof_get_intlw(I, number) iof_get_int64(I, number) +# define iof_get_uintlw(I, number) iof_get_uint64(I, number) +# define iof_get_intlw_radix(I, number, radix) iof_get_int64_radix(I, number, radix) +# define iof_get_uintlw_radix(I, number, radix) iof_get_uint64_radix(I, number, radix) +#elif defined(INTLW_IS_LONG) +# define iof_get_intlw(I, number) iof_get_slong(I, number) +# define iof_get_uintlw(I, number) iof_get_ulong(I, number) +# define iof_get_intlw_radix(I, number, radix) iof_get_slong_radix(I, number, radix) +# define iof_get_uintlw_radix(I, number, radix) iof_get_ulong_radix(I, number, radix) +#endif + +UTILAPI int iof_get_roman (iof *I, uint16_t *number); UTILAPI int iof_get_double (iof *I, double *number); UTILAPI int iof_get_float (iof *I, float *number); @@ -529,29 +528,41 @@ UTILAPI int iof_conv_float (iof *I, float *number); /* number to iof; return a number of written bytes */ UTILAPI size_t iof_put_int32 (iof *O, int32_t number); -UTILAPI size_t iof_put_intlw (iof *O, intlw_t number); +UTILAPI size_t iof_put_slong (iof *O, long number); UTILAPI size_t iof_put_int64 (iof *O, int64_t number); UTILAPI size_t iof_put_uint32 (iof *O, uint32_t number); -UTILAPI size_t iof_put_uintlw (iof *O, uintlw_t number); +UTILAPI size_t iof_put_ulong (iof *O, unsigned long number); +UTILAPI size_t iof_put_usize (iof *O, size_t number); UTILAPI size_t iof_put_uint64 (iof *O, uint64_t number); -UTILAPI size_t iof_put_int32_radix (iof *O, int32_t number, int radix); -UTILAPI size_t iof_put_intlw_radix (iof *O, intlw_t number, int radix); -UTILAPI size_t iof_put_int64_radix (iof *O, int64_t number, int radix); - -UTILAPI size_t iof_put_uint32_radix (iof *O, uint32_t number, int radix); -UTILAPI size_t iof_put_uintlw_radix (iof *O, uintlw_t number, int radix); -UTILAPI size_t iof_put_uint64_radix (iof *O, uint64_t number, int radix); +UTILAPI size_t iof_put_int32_radix (iof *O, int32_t number, int radix, int uc); +UTILAPI size_t iof_put_slong_radix (iof *O, long number, int radix, int uc); +UTILAPI size_t iof_put_int64_radix (iof *O, int64_t number, int radix, int uc); + +UTILAPI size_t iof_put_uint32_radix (iof *O, uint32_t number, int radix, int uc); +UTILAPI size_t iof_put_ulong_radix (iof *O, unsigned long number, int radix, int uc); +UTILAPI size_t iof_put_usize_radix (iof *O, size_t number, int radix, int uc); +UTILAPI size_t iof_put_uint64_radix (iof *O, uint64_t number, int radix, int uc); + +#if defined(INTLW_IS_INT64) +# define iof_put_intlw(O, number) iof_put_int64(O, number) +# define iof_put_uintlw(O, number) iof_put_uint64(O, number) +# define iof_put_intlw_radix(O, number, radix, uc) iof_put_int64_radix(O, number, radix, uc) +# define iof_put_uintlw_radix(O, number, radix, uc) iof_put_uint64_radix(O, number, radix, uc) +#elif defined(INTLW_IS_LONG) +# define iof_put_intlw(O, number) iof_put_slong(O, number) +# define iof_put_uintlw(O, number) iof_put_ulong(O, number) +# define iof_put_intlw_radix(O, number, radix, uc) iof_put_slong_radix(O, number, radix, uc) +# define iof_put_uintlw_radix(O, number, radix, uc) iof_put_ulong_radix(O, number, radix, uc) +#endif -UTILAPI size_t iof_put_roman_uc (iof *O, uint16_t number); -UTILAPI size_t iof_put_roman_lc (iof *O, uint16_t number); -#define iof_put_roman(I, number) iof_put_roman_uc(I, number) +UTILAPI size_t iof_put_roman (iof *O, uint16_t number, int uc); UTILAPI size_t iof_put_double(iof *O, double number, int digits); UTILAPI size_t iof_put_float(iof *O, float number, int digits); -/* common stuff for binary integers */ +/* common helpers for binary parsers */ UTILAPI int iof_get_be_uint2 (iof *I, uint32_t *pnumber); UTILAPI int iof_get_be_uint3 (iof *I, uint32_t *pnumber); @@ -585,8 +596,8 @@ UTILAPI int iof_get_le_uint4 (iof *I, uint32_t *pnumber); /* buffer results */ -#define iof_reader_result(I, size) ((size = iof_left(I)), (I)->pos) -#define iof_writer_result(I, size) ((size = iof_size(I)), (I)->buf) +#define iof_reader_result(I, size) ((size = (size_t)iof_left(I)), (I)->pos) +#define iof_writer_result(I, size) ((size = (size_t)iof_size(I)), (I)->buf) #define iof_result(I, size) (((I)->flags & IOF_READER) ? iof_reader_result(I, size) : iof_writer_result(I, size)) uint8_t * iof_file_input_data (iof_file *iofile, size_t *psize, int *isnew); @@ -612,13 +623,6 @@ UTILAPI void iof_debug (iof *I, const char *filename); void iof_filters_init (void); void iof_filters_free (void); -void * iof_filter_new (size_t size); -void iof_heap_back (void *data); -#define iof_filter_free(F) iof_heap_back(F) -#define iof_filter_buffer_free(data) iof_heap_back(data) - -// &((void *)pstate - iof * iof_filter_reader_new (iof_handler handler, size_t statesize, void **pstate); #define iof_filter_reader(handler, statesize, pstate) iof_filter_reader_new(handler, statesize, (void **)(pstate)) iof * iof_filter_reader_with_buffer_new (iof_handler handler, size_t statesize, void **pstate, void *buffer, size_t buffersize); @@ -628,7 +632,7 @@ iof * iof_filter_writer_new (iof_handler handler, size_t statesize, void **pstat iof * iof_filter_writer_with_buffer_new (iof_handler handler, size_t statesize, void **pstate, void *buffer, size_t buffersize); #define iof_filter_writer_with_buffer(handler, statesize, pstate, buffer, buffersize) iof_filter_writer_with_buffer_new(handler, statesize, (void **)(pstate), buffer, buffersize) -#define iof_filter_state(statetype, F) (statetype)((F) + 1) +#define iof_filter_state(statetype, F) (statetype)((void *)((F) + 1)) void iof_free (iof *F); void iof_discard (iof *F); diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utillog.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utillog.c index 1b38f74679c..6d32514a7a7 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utillog.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utillog.c @@ -21,40 +21,40 @@ void loggerf (const char *format, ...) { va_list args; int length; - - va_start(args, format); + + va_start(args, format); length = vsnprintf(logger_buffer + logger.pfxlen, LOGGER_BUFFER_SIZE, format, args); - if (length > 0) - { - if (length > LOGGER_BUFFER_SIZE) - length = LOGGER_BUFFER_SIZE; - } - else - { - loggerf("logger encoding error '%s'", format); - length = (int)strlen(logger_buffer); - } - length += (int)logger.pfxlen; - if (logger.callback) - logger.callback(logger_buffer, logger.context); + if (length > 0) + { + if (length > LOGGER_BUFFER_SIZE) + length = LOGGER_BUFFER_SIZE; + } + else + { + loggerf("logger encoding error '%s'", format); + length = (int)strlen(logger_buffer); + } + length += (int)logger.pfxlen; + if (logger.callback) + logger.callback(logger_buffer, logger.context); else - printf("\n%s\n", logger_buffer); - va_end(args); + printf("\n%s\n", logger_buffer); + va_end(args); } void logger_callback (logger_function callback, void *context) { - logger.callback = callback; - logger.context = context; + logger.callback = callback; + logger.context = context; } int logger_prefix (const char *prefix) { - size_t pfxlen; - pfxlen = strlen(prefix); - if (pfxlen > LOGGER_PREFIX_SIZE) - return 0; - memcpy(logger_buffer, prefix, pfxlen); - logger.pfxlen = pfxlen; - return 1; + size_t pfxlen; + pfxlen = strlen(prefix); + if (pfxlen > LOGGER_PREFIX_SIZE) + return 0; + memcpy(logger_buffer, prefix, pfxlen); + logger.pfxlen = pfxlen; + return 1; } diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utillog.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utillog.h index c30e0ff0f57..c30e0ff0f57 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utillog.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utillog.h diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utillzw.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utillzw.c index 4cd22121449..e5134e79473 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utillzw.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utillzw.c @@ -204,6 +204,10 @@ struct lzw_state { int flags; /* options */ }; +typedef union { lzw_state *lzwstate; void *voidstate; } lzw_state_pointer; // to avoid 'dereferencing type-puned ...' warnings + +#define LZW_INIT_STATE { { 0 }, 0, { 0 }, 0, 0, 0, 0, 0, 0 } + /* macros */ #define LZW_MIN_BITS 3 @@ -583,7 +587,7 @@ iof_status lzw_encode_state (iof *I, iof *O, lzw_state *state) iof_status lzw_decode (iof *I, iof *O, int flags) { - lzw_state state = { { 0 } }; // shut overactive warnings + lzw_state state = LZW_INIT_STATE; lzw_entry table[LZW_TABLE_SIZE]; int ret; lzw_decoder_init_table(&state, table, flags); @@ -596,7 +600,7 @@ iof_status lzw_decode (iof *I, iof *O, int flags) iof_status lzw_encode (iof *I, iof *O, int flags) { - lzw_state state; + lzw_state state = LZW_INIT_STATE; lzw_node lookup[LZW_LOOKUP_SIZE]; int ret; lzw_encoder_init_table(&state, lookup, flags); @@ -653,7 +657,7 @@ static size_t lzw_encoder (iof *F, iof_mode mode) { case IOFFLUSH: state->flush = 1; - // fall through + FALLTHRU // fall through case IOFWRITE: F->end = F->pos; F->pos = F->buf; @@ -674,25 +678,25 @@ static size_t lzw_encoder (iof *F, iof_mode mode) iof * iof_filter_lzw_decoder (iof *N, int flags) { iof *I; - lzw_state *state; - I = iof_filter_reader(lzw_decoder, sizeof(lzw_state), &state); + lzw_state_pointer P; + I = iof_filter_reader(lzw_decoder, sizeof(lzw_state), &P.voidstate); iof_setup_next(I, N); - if (lzw_decoder_init(state, flags) == NULL) + if (lzw_decoder_init(P.lzwstate, flags) == NULL) { iof_discard(I); return NULL; } - state->flush = 1; + P.lzwstate->flush = 1; return I; } iof * iof_filter_lzw_encoder (iof *N, int flags) { iof *O; - lzw_state *state; - O = iof_filter_writer(lzw_encoder, sizeof(lzw_state), &state); + lzw_state_pointer P; + O = iof_filter_writer(lzw_encoder, sizeof(lzw_state), &P.voidstate); iof_setup_next(O, N); - if (lzw_encoder_init(state, flags) == NULL) + if (lzw_encoder_init(P.lzwstate, flags) == NULL) { iof_discard(O); return NULL; diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utillzw.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utillzw.h index 9e3a085d43c..9e3a085d43c 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utillzw.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utillzw.h diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmd5.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmd5.c new file mode 100644 index 00000000000..871984229c2 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmd5.c @@ -0,0 +1,447 @@ + +/* md5 implementation excerpted from code by Peter Deutsch */ + +/* begin of md5.c */ + +/* + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.c is L. Peter Deutsch + <ghost@aladdin.com>. Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order + either statically or dynamically; added missing #include <string.h> + in library. + 2002-03-11 lpd Corrected argument list for main(), and added int return + type, in test program and T value program. + 2002-02-21 lpd Added missing #include <stdio.h> in test program. + 2000-07-03 lpd Patched to eliminate warnings about "constant is + unsigned in ANSI C, signed in traditional"; made test program + self-checking. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#include <string.h> // memcpy +#include <stdio.h> // FILE + +#include "utilmd5.h" + +#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#ifdef ARCH_IS_BIG_ENDIAN +# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) +#else +# define BYTE_ORDER 0 +#endif + +#define T_MASK ((uint32_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) + +static void md5_process (md5_state *state, const uint8_t *data /*[64]*/) +{ + uint32_t + a = state->words[0], b = state->words[1], + c = state->words[2], d = state->words[3]; + uint32_t t; +#if BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + uint32_t X[16]; +#else + /* Define storage for little-endian or both types of CPUs. */ + uint32_t xbuf[16]; + const uint32_t *X; +#endif + + { +#if BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; + + if (*((const uint8_t *)&w)) /* dynamic little-endian */ +#endif +#if BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (const uint8_t *)0) & 3)) { + /* data are properly aligned */ + X = (const uint32_t *)((const void *)data); // avoid compiler warning + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } +#endif +#if BYTE_ORDER == 0 + else /* dynamic big-endian */ +#endif +#if BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const uint8_t *xp = data; + int i; +# if BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ +# else +# define xbuf X /* (static only) */ +# endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } +#endif + } + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + state->words[0] += a; + state->words[1] += b; + state->words[2] += c; + state->words[3] += d; +} + +/* api */ + +md5_state * md5_digest_init (md5_state *state) +{ + state->bitcount[0] = state->bitcount[1] = 0; + state->words[0] = 0x67452301; + state->words[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + state->words[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + state->words[3] = 0x10325476; + return state; +} + +void md5_digest_add (md5_state *state, const void *input, size_t size) +{ + const uint8_t *p = (const uint8_t *)input; + int nbytes = (int)size; // PJ + int left = nbytes; + int offset = (state->bitcount[0] >> 3) & 63; + uint32_t nbits = (uint32_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + state->bitcount[1] += nbytes >> 29; + state->bitcount[0] += nbits; + if (state->bitcount[0] < nbits) + state->bitcount[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(state->buffer + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(state, state->buffer); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(state, p); + + /* Process a final partial block. */ + if (left) + memcpy(state->buffer, p, left); +} + +#define md5_digest_byte(state, i) (uint8_t)(state->words[i >> 2] >> ((i & 3) << 3)) + +void md5_digest_get (md5_state *state, uint8_t digest[], int flags) +{ + static const uint8_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + uint8_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (uint8_t)(state->bitcount[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_digest_add(state, pad, ((55 - (state->bitcount[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_digest_add(state, data, 8); + + /* Output */ + if (flags & MD5_HEX) + { // expected digest buffer size MD5_STRING_LENGTH + uint8_t byte; + const char *alphabet; + alphabet = (flags & MD5_LCHEX) ? "0123456789abcdef" : "0123456789ABCDEF"; + for (i = 0; i < MD5_DIGEST_LENGTH; ++i) + { + byte = md5_digest_byte(state, i); + *digest++ = (uint8_t)alphabet[byte >> 4]; + *digest++ = (uint8_t)alphabet[byte & 15]; + } + *digest = 0; + } + else + { // expected digest buffer size MD5_DIGEST_LENGTH + for (i = 0; i < MD5_DIGEST_LENGTH; ++i) + *digest++ = md5_digest_byte(state, i); + } +} + +void md5_digest (const void *input, size_t length, uint8_t digest[], int flags) +{ + md5_state md5; + md5_digest_init(&md5); + md5_digest_add(&md5, input, length); + md5_digest_get(&md5, digest, flags); +} + +/* file checksum */ + +#define DIGEST_BUFFER_SIZE 4096 + +int md5_digest_add_file (md5_state *state, const char *filename) +{ + FILE *fh; + uint8_t buffer[DIGEST_BUFFER_SIZE]; + size_t read; + + if ((fh = fopen(filename, "rb")) == NULL) + return 0; + do { + read = fread(buffer, 1, DIGEST_BUFFER_SIZE, fh); + md5_digest_add(state, buffer, read); + } while (read == DIGEST_BUFFER_SIZE); + fclose(fh); + return 1; +} + +int md5_digest_file (const char *filename, uint8_t digest[], int flags) +{ + md5_state state; + + md5_digest_init(&state); + if (md5_digest_add_file(&state, filename)) + { + md5_digest_get(&state, digest, flags); + return 1; + } + return 0; +}
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmd5.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmd5.h new file mode 100644 index 00000000000..3964d59df21 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmd5.h @@ -0,0 +1,49 @@ + +/* sha2 implementation excerpted from code by Aaron D. Gifford */ + +#ifndef UTIL_MD5_H +#define UTIL_MD5_H + +#include <stdint.h> +#include <stddef.h> // for size_t +#include "utildecl.h" + +//#define md5_state md5_state_t + +typedef struct { + uint32_t bitcount[2]; + uint32_t words[4]; + uint8_t buffer[64]; +} md5_state; + +#define MD5_DIGEST_LENGTH 16 +#define MD5_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) + +enum { + MD5_BYTES = 0, + MD5_UCHEX = (1<<0), + MD5_LCHEX = (1<<1) +}; + +#define MD5_DEFAULT MD5_BYTES +#define MD5_HEX (MD5_UCHEX|MD5_LCHEX) + +#ifdef __cplusplus +extern "C" +{ +#endif + +UTILAPI md5_state * md5_digest_init (md5_state *state); +UTILAPI void md5_digest_add (md5_state *state, const void *input, size_t size); +UTILAPI void md5_digest_get (md5_state *state, uint8_t digest[], int flags); + +UTILAPI void md5_digest (const void *input, size_t length, uint8_t digest[], int flags); + +UTILAPI int md5_digest_add_file (md5_state *state, const char *filename); +UTILAPI int md5_digest_file (const char *filename, uint8_t digest[], int flags); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilmem.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmem.c index 1fa00a0c10a..9a32247ab11 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilmem.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmem.c @@ -49,9 +49,8 @@ allocated -- flag indicating if *data has been allocated (with malloc) void util_resize (void **data, size_t unit, size_t size, size_t extra, size_t *space, int allocated) { if (*space == 0) - *space = 4; // ... better keep *space non-zero to avoid it - do { *space <<= 1; } - while (size + extra > *space); + *space = 4; // better keep *space non-zero to avoid it + do { *space <<= 1; } while (size + extra > *space); if (allocated) { diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmem.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmem.h new file mode 100644 index 00000000000..4cfcfaba2a7 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmem.h @@ -0,0 +1,16 @@ + +#ifndef UTIL_MEM_H +#define UTIL_MEM_H + +#include <stdlib.h> // for size_t and alloc functions +#include "utildecl.h" + +UTILAPI void * util_malloc (size_t size); +UTILAPI void * util_calloc (size_t num, size_t size); +UTILAPI void * util_realloc (void *m, size_t size); + +void util_resize (void **data, size_t unit, size_t size, size_t extra, size_t *space, int allocated); + +#define util_free free // not a call, might be used as identifier + +#endif diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemallc.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemallc.h new file mode 100644 index 00000000000..57d268cf733 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemallc.h @@ -0,0 +1,561 @@ +/* +Allocators +========== + +Using allocators defined here makes sense if there is a need to take a space for rather large amount of rather small objects. +The basic idea is to take memory in reasonably large blocks and to distribute small chunks from those blocks. Once chunks are +no longer needed, one can free them all at once, or free taken chunks individually. + +We define 3 types of allocators: + +1. HEAP - the simplest one, provides variable length memory chunks from larger blocks and frees them all on explicit + request. There is no way to free individual objects, only the entire heap. The heap only grows, until freed. + +2. STOCK - provides variable length memory chunks from larger blocks, but allows to free individual objects as well as the + entire stock. The stock grows and shrinks, by leaps and bounds, depending on parameters given during initialization. + +3. POOL - provides fixed size memory chunks from larger blocks. It allows to free individual chunks as well as the entire pool. + In opposite to a stock, a pool also reuses a space reclaimed by freeing individual objects; before allocating a new block it + firsts recycles freed chunks, if any. + +In general, memory chunks provided by allocators are never reallocated. Allocators do nothing with provided chunks until freed. + +Allocators are represented as small structures (several pointers and integers). We assume that such structures are either static +variables, or members of larger structures. We don't bother to allocate a memory for them. Usage scheme is pretty similar for +all: + + init() - just inititalize, don't allocate anything yet + take() - take chunks + take() + take() + ... + free() - free the all at once + +For stocks and pools there is a possibility to give back individual chunks: + + init() - like above + take() - take chunks + take() + take() + back() - give chunks back when no longer needed + take() + back() + ... + free() - needed only if not all chunks have been given back + +All calls take a shell structure pointer as an argument. take() returns a void pointer, aligned according to used variant +(8, 16, 32, 64). back() takes a void pointer as the second argument. It must be the pointer previously returned by take(). + +back() can be called in any order and can obviously be plotted with take(). By default, after back()-ing all taken chunks, the +stock returns to its initial state (zero memory used). A special KEEP flag can be used during initialization to prevent +freeing the last (sole) allocated block. If KEEP option is used, the allocator always keeps a single segment for further +allocations. This is necessary only when there is a risk that just several take() calls will be immediatelly followed by the +same number of back() calls. KEEP flag prevents allocating and freeing rather large blocks just to serve several chunks. And +this is actually important only if there are no other blocks taken, that is, if there is only one, nearly empty block in use. +In other cases KEEP flag doesn't matter, but allocators takes care to always have a block for fast allocs. + +There is also clear() operation that frees all but the recent block. One can use it to free all chunks taken so far, but to +make the allocator ready for further allocs. If either KEEP flag is used or clear() is called, soner or later the user have to +call free() explicitly, to remove all the remaining memory kept by the allocator. There is no KEEP flag for heaps, as heaps +don't allow to free individual chunks. And so, the heap never needs to make a decision if the last sole block should be removed +or not. The user makes the decision by calling clear() vs free() respectively. + +Pop +=== + +A very last chunk taken can be quickly given back with + + pop(heap, taken, size) // for heap or stock + pop(pool, taken) // for pool + +taken must be the chunk returned by the very last take(), size must be the size requested. If the chunk has been taken from +the head block (more about blocks below), the block pointer returns to its previous position, as it was before the last take(). +If the chunk has been taken from the sole block beneatch the head, the entire sole block (containing just that single chunk) +is freed. The pop() operation is different than back(); the popped chunk doesn't cause freeing the head block when its refcount +gets zero. So pop() operation breaks the concept of stock that frees all the memory once all taken chunks are given back. +on the other hand, if for some reason the very last taken chunk is to be ignored, pop() is better, as it doesn't cause blocks +scattering. The popped chunk pointer will probably be returned by the very next call to take(). In case of heap, pop() is +the only way to discard the chunk, as there is no back() operation. + +Buffer interface +================ + +When heap or stock is used by parsers, the caller oftenly doesn't know how many space will be needed for a data (this doesn't +apply to pools, which returns constant size memory chunks). Here is an interface for the allocator-as-bufer case (same for +heap and stock): + + some(heap, atleast, &space); + more(heap, taken, written, space); + ... + done(heap, taken, written); + +some() operation provides a data pointer to at least a given bytes. The actual space provided for writing is set to the third +argument. The caller may write space-bytes. If more space is needed, more() operation takes care to provide a chunk for a given +amount of bytes (space) and rewrites already written amount of bytes from a previous chunk to a new location. The function takes +the pointer to the chunk previously taken; the one returned by some() or more(). This argument must not be NULL. If you don't want +to copy a data, set written argument to zero. No matter if more() operation was used zero, one or multiple times, all the cycle must +end with done(). Calls triple - some(), more() and done() - must not be interrupted by any other api calls. In particular, using take() +or back() smells like a segfault. However, if there is a need discard the buffer being written (eg. input data error), instead of +done() one may use + + giveup(heap, taken) + +If done() has already been called, pop() is the only option to discard the chunk + + pop(heap, taken, written) + +some() operation usually doesn't change the state of the heap, unless the heap head block is NULL, or atleast parameter is too +large to fit the remaining block. more() usually changes the state, either by allocating a new head block, or by allocating +a sole block just beneath the head (blocks and blocks tiling mechanism are described below). If a sole block has been taken for +some large chunk subsequent calls to more() reallocate this sole block in place. It is assumed, that the size you request in subsequent +calls generally grows. It is ok to request space-bytes, then call done() with written value less then requested. But the drawback +is that if the chunk has already been allocated from a sole chunk, the space requested but not used is a waste. + +iof interface +============= + +iof is an independent interface for buffers written/read byte-by-byte. If used together with allocators, the provides a convenient +way to write byte data to the heap or stock, without a need for intermediate buffers. The idea is to have iof buffer always ready +for writing into the heap or stock. The buffer is setup just once, with + + iof *output = buffer_init(heap, iof) // calls some(heap, 0) + +Then one can write to iof with + + iof_put(output, char); + iof_write(output, string); + iof_ensure(output, bytes); + .... + +iof keeps pointers to the beginning of buffer, end of buffer, and current position. Once the position reaches the end, the iof +internal handler updates the buffer providing more space to write. In that case, updating the buffer means settings buf/pos/end +pointers according to a data pointer and space returned by more(). From the user perspective, this pretends a countinuous space +for writing, without bothering about buffer boundaries. + +Once you are done with writing some chunk + + iof_flush() // calls done() and some() again + +updates the underlying heap or stock, and makes the iof ready for a new chunk. iof it self does not allocate a memory, so it +doesn't need finalizer, iof_close(output) does nothing. So the cycle looks as follows: + + buffer_init(heap, iof) + <write to iof> ... iof_flush(iof) + <write to iof> ... iof_flush(iof) + ... + +More often then not, we need to specify a minimal space for buffer each time, eg. for memcpy() or so. The actual space left +can be checked with iof_left(iof), the space for recent chunk is iof->space. + +We can also work as follows: + + buffer_init(heap, iof) + buffer_some(heap, iof) ... <write to iof> ... data = iof_writer_result(iof, &size) + buffer_some(heap, iof) ... <write to iof> ... data = iof_writer_result(iof, &size) + ... + +Identical interface for heap and stock. + +Blocks +====== + +Each alloctor structure keeps a pointer to a head block, initially NULL. Most of new chunks are taken from the head. Once the +space left in the head block is to small to provide a chunk of requested size, a new head is created and the previous one is +linked to the head (blocks form a linked list). A stock block is named a ream, a heap block is named a pyre, a pool block is +named pile (we need to distinguish structure names in code but in the description below they are all called blocks). Every +block knows a number of chunks taken from that block (refcont). A stock also keeps a number of freed chunks [actually only +for statistics; in most cases it doesn't need an extra space in struct ream, as thies structure member lays in the place +f padding bytes.] + +We change the head block only if the new block is allocated, but we never change the head backward. Once some block became +->prev, it will never became a head again. This ensures that the allocator have the head block that usually has a lot of space +for new allocs. This needs a special care when removing a block that is not a head block. We check if the next block to the one +being removed is the head. If it is, and if its refcount is zero (and no KEEP flag is used) the head is removed as well. + +The basis of pools is similar to stocks and heaps, but there are some significant differences. A pool servers memory chunks of +equal size, specified during initialization. This also means that the pool knows the boundaries of individual chunks (stock and +heap doesn't). A pool provides iterators over chunks in use (taken but not given back yet). A pool shell structure keeps +a pointer to a head block and a tail block (both may point a different block, the same block or NULL). This is necessary only +for iterators to let the user follow the chunks from the first or from the last taken. The extra cost of maintaining both +->head and ->tail is neglectable. + +Refcounting +=========== + +Heap refcounting: whenever a new chunk is taken, the block refcount is incremented. It is never decremented, but plays an +important role in block tiling algorithm (below). No KEEP flag is used here. All the blocks are removed on free(), all but +recent are removed on clear(). + +Stock refcounting: whenever a new chunk in taken from the block, the block refcount is incremented. Whenever the chunk is given +back, the refcount is decremented. When the refcount gets zero, the block is removed and freed. To remove the block from the +list (any block, not necessarily a head block), a stock needs 2-directional list; every block has ->next and ->prev links. The +head block of the stock is freed only if this is the last (sole) block and no KEEP flag was used during initialization. +Otherwise the block is just reset, becoming ready for further allocations - refcount gets zero, data space reset to an initial +state. + +Pool refcounting: pretty much like with stocks, except that any chunk given back can be recycled on further take(). + +Ghosts +====== + +Every allocated block starts with a private structure for next/prev links, data pointer, refcount. We call it a block ghost. +Except from heap, individual chunks also need a ghost (chunk ghost) so that we are able to know from which block the chunk +comes from once the chunk is given back by the user (heaps don't have back() operation so data chunks have no ghosts). We keep +ghosts possibly small. Chunk ghosts are of size natural for alignment variant (1, 2, 4 or 8 bytes). Block ghosts are somewhat +larger. Statistics show clearly that it is worthy to keep them as small as possible: +- chunk ghosts keep offset to the block ghost, not a pointer to it (we use the pointer only if it makes no difference + to the chunk size; 64-bit aligned variant on 64-bit machine, 32 and 64 variants on 32-bit machine) +- block ghosts uses a data pointer (not an offset) so that we are able to record any requested chunk size (size_t) and to avoid + long array indexing on every chunk request + +At some point we considered storing a sheel structure pointer in the block ghost, then back() operation wouldn't need an extra +argument. But stats showed that the size of the block ghost is the most significant factor in memory usage efficiency, so eliminating +this extra pointer pays off. Besides, this would make impossible to relocate the shell structure. We don't allocate a memory +for the shell, so we shouldn't make assumptions of shell structure address. + +Tiling algorithm +================ + +Tiling the block size refers to stocks and heaps that serves memory chunks of variable size. Both stock and heap performs best +when the average size of requested chunks is a way smaller that the configured block size. But both also put no limitations on +chunk sizes, so they need to cope with situation, where the requested size is quite large, eg. half of the block size or even +more than the block size. Here is the algorithm used for blocks tiling: + +1. When the requested chunk size fills in the recent block, just serve it from that block. This is the best and hopefully the + most common case. + +2. When the requested chunk size is larger that the space left in the recent block, the new block must be allocated. But there +are two ways: + + a) either replace the head block with the new block so that the list of blocks is + + ... <- prev <- head so far <- new head + + b) or insert the block just "below the head", keeping the head intact, + + ... <- prev <- new single head <- head + +The first is the regular case. It is used when the space left in the head so far is small (can be neglected), and the requested +size is relatively small (will fit the new block). If the space left in the head block is worthy to bother, or the requested +chunk size is rather large, the new chunk is served from a single block, allocated just for that chunk. The block is of the +size needed for that chunk. The block never becomes the head, no other chunks will be served from it (its refcount is +permanently 1, until freed). + +Much depends on what is considered 'small, neglectable block space' and 'rather large chunk size'. The later is easier to +imagine. When the requested size is larger than the block size used for a given allocator, then the size is definitelly +considered large. When it is smaller than the block size, but still large enough to occupy most of the block size (grabbing +quite some space for tiny chunks), it is also considered large. As the block size, what is considered 'large' can be spcified +during initialization. A setup that works fine for me is (large = block_size / 2). + +Making a decision what is the left block space we can neglect is quite not obvious. At first approach we used a constant value, +requested from the user during allocator initialization. But it is hard to select a good default. Now we compute this value +from block params, by dividing a complete space occupied so far in the block by the number of chunks served from that block +(the average size of chunks allocated from this block). We assume that the average chunk size (or smaller) is the space we can +neglect. The logic behind is the following: if the space left in the block is larger than the average, it makes sense not to +waste this space and keep it for further allocs. If the space left in the block is less than the average, there is only a little +chance we will get a request for suitable size, so we sacrifice that space and we start allocating from a new block. + +Statistics showed a caveat in average == treshold approach. Suppose we have a block that has the average chunk size 16, there +is 18 bytes left in the block (not neglectable), and the user request is 20 bytes. Allocating a single block for 20 bytes is +bad, because the block ghost is 24 bytes (more internal than allocated memory). Allocating many of such blocks gives bad results; +much more allocs than necessary, large waste. To avoid that, we help to neglect the remaining block space by checking if the +space left is smaller than the block ghost size, which is an inevitable cost anyway. + +Stats below shows clearly that we should rather focus on "how to avoid producing sole-chunk blocks" instead of "how to feel the +remaining space". + +Recycling +========= + +Recycling applies only to pools. When a chunk is given back, it is inserted into a list of items for recycling. Every pool +block keeps a head of that list. Once a chunk is given back, it is inserted as recycling head and the previous head is attached +to a new head. Since every chunk is associated with a ghost, we use ghosts to store a link (pointer or offset) to another item +for recycling. Note that the ghost always keeps either a link to the block it belongs to, or a link to another recyclable ghost +of the same block. This is used by iteratos to distinguish the chunk currently in use from the chunk that has already been +given back; if the link points the block, the chunk is in use. + +A pool block that has at least one recyclable chunk is called a squot. A pool shell structure keeps 2-directional list of +squots. Once a pool block becomes a squot, it is inserted to that list. Once its all recyclable items has been used, it is +removed from the squots list. In every moment, the pool has an access to a list of all squots, and therefore, to a list of all +recyclable items. + +Whenever there is a request for a new chunk, at first it is served from the head block, as this is the easiest and the cheapest way. +Once the recent block has no more place for new items, recycling list is used, starting from the head recyclable chunk of the head squot. +In practise this is always the most recently reclaimed chunk ghost. During further allocs, a pool will first utilize all recyclables +from all squots before allocating a new block. + +Stats +===== + +Some numbers. The test made on a stock8, block size 255 bytes, 10000 allocations, random chunk sizes from 1 to 32 bytes +(average 16). These are rather tight constraints because of 255 buffer limit. First approach: + + blocks: 903 - this is the actual number of malloc() calls + singles: 214, 23.70% of all blocks + waste: 20.16% - total memory that was allocated but not requested by the user + block ghosts 10.04%, plus single block ghosts 3.12% + chunk ghosts 4.55% + neglected block tails 2.45% + +After adding a test for left space that helps in 'neglect remainig space or make sole chunk block' decision: + + blocks: 723 - a way better + singles 0 + waste: 19.04% - slightly better + block ghosts 10.67% + chunk ghosts 4.61% + neglected block tails 3.76% + +The actual numbers vary depending on the buffer size, the average elements size and, of course, taken alignment variant. After +some parameters tuning, on various tests we get 5-19% total waste for stocks, 3-14% total waste for heaps. But the basic scheme +of statistics remains similar: we take relatively lots of space for blocks ghost (5-10% of total memory taken), some inevitable +space for chunk ghosts (varies, 4-13% on various tests), and a little waste of neglected block tails (2-4%). Quite +surprisingly, block ghosts are, in sum, oftenly more significant than individual chunk ghosts (for the test above over half of +all the waste!). The number of block ghosts (equals the number of blocks) mostly depends on block size vs chunk size relation. +But seemingly it is worthy to bother about the size of the block ghost and the number of blocks taken - the less the better. +The waste of ghosts of individual objects (stock and pool) is inevitable, and depends only on the number/size of objects taken. +We can't use smaller ghosts, we can't do better. Anyways, the least significant is the waste of neglected block tails. + +Pools stats are pretty similar, but more predictable because of known chunks size. A pool block ghost is somewhat larger +structure because it keeps ->nextsquot / ->prevsquot pointers among ->next / ->prev. On the other hand, it doesn't need +->unused counter, as for fixed-length chunks it can always be computed from the refcount and used data. Also somewhat larger +block ghost structure is compensated by the fact that the are no tail block waste and there is no 'neglect or not' problem. + +Alignment +========= + +Each allocator has 4 variants for 1, 2, 4, 8 bytes alignment respectively. Eg. stock32_take() always returns a pointer aligned +to 4 bytes, heap64_take() returns a pointer aligned to 8 bytes. You can ask for any data length, but in practise you'll always +obtain 1N, 2N, 4N or 8N. Alignment implies data padding unless the user requests for "aligned" sizes. In statistics the padding +is not considered a waste. +*/ + +#ifndef UTIL_MEM_ALLC_C +#define UTIL_MEM_ALLC_C + +/* +Common internals for allocators suite. A selection or all of the following defines (from api headers) should already be there: + + UTIL_MEM_HEAP_H // utilmemheap.h + UTIL_MEM_STOCK_H // utilmemstock.h + UTIL_MEM_POOL_H // utilmempool.h + +*/ + +#include <string.h> // memset() +#include <stdio.h> // printf() + +#include "utilmem.h" +//#include "utilmemallh.h" + +#if 0 // for a while +# define ASSERT8(cond) (void)0 +# define ASSERT16(cond) (void)0 +# define ASSERT32(cond) (void)0 +# define ASSERT64(cond) (void)0 +#else +# define ASSERT8(cond) ((void)((cond) || (printf("8bit allocator assertion, %s:%d: %s\n", __FILE__, __LINE__, #cond), 0))) +# define ASSERT16(cond) ((void)((cond) || (printf("16bit allocator assertion, %s:%d: %s\n", __FILE__, __LINE__, #cond), 0))) +# define ASSERT32(cond) ((void)((cond) || (printf("32bit allocator assertion, %s:%d: %s\n", __FILE__, __LINE__, #cond), 0))) +# define ASSERT64(cond) ((void)((cond) || (printf("64bit allocator assertion, %s:%d: %s\n", __FILE__, __LINE__, #cond), 0))) +#endif + +#if defined(UTIL_MEM_STOCK_H) || defined(UTIL_MEM_POOL_H) +struct ghost8{ + uint8_t offset; +}; + +struct ghost16 { + uint16_t offset; +}; + +#ifdef BIT32 +struct ghost32 { + union { +#ifdef UTIL_MEM_STOCK_H + ream32 *ream; +#endif +#ifdef UTIL_MEM_POOL_H + pile32 *pile; + ghost32 *nextfree; +#endif + void *block; + }; +}; +#else +struct ghost32 { + uint32_t offset; +}; +#endif + +struct ghost64 { + union { +#ifdef UTIL_MEM_STOCK_H + ream64 *ream; +#endif +#ifdef UTIL_MEM_POOL_H + pile64 *pile; + ghost64 *nextfree; +#endif + void *block; + }; +#ifdef BIT32 + uint8_t dummy[4]; // force 8 +#endif +}; +#endif + +/* +All offsets related macro horror is here. Block is 4/8-bytes aligned (32/64 pointer size), ream->data is adjusted to 1/2/4/8-bytes accordingly. +Therefore all offsets we store and pointers we cast, should be properly aligned. In all cases, sizes and offsets refers to bytes. +We need data ghosts only to access the block. For 8 and 16 we use 8/16 bit offsets to keep the ghost smaller. For 32 and 64 we either use offset, +or a pointer to the ream. + +malloc() is obviously expected to return a pointer properly allowed for all standard c-types. For 64-bit we can safely expect at least 8-bytes aligned. +(at least, because long double may need 16 bytes on gcc64, or 8 bytes on msvc64, or weird on some exotics). On 32 bit machines pointers are 4 bytes +aligned, even long long is 4-bytes aligned. But double on 32bit machine is 8-bytes aligned on windows, 4 bytes aligned in linux (compiler option +-malign-double makes it 8-bytes aligned). Anyways, we cannot expect that on 32bit machine the result of malloc is always 8-bytes aligned. +This requires a very special treatment of 64-variant on 32bit machine: the first data ghost may need to be 4-bytes off. Should we ensure 4 bytes +more from malloc just in case? Hmm padding will be there anyway, as we adjust ream->data size to bytes boundaries. + +In both 32/64bit environments, the ghost keeps a pointer to the block. On 32bit machine, the first chunk ghost address may need to be +4, +as this is not ensured by malloc(). See struct ream64 {}. We have an extra test; the final ghost pointer will be properly aligned iff + + ((block & 7 == 0) && (sizeof(block64) & 7 == 0)) || ((block & 7 == 4) && (sizeof(block64) & 7 == 4) + +or in short + + ((block + 1) & 7) == 0 + +otherwise it needs 4 bytes offset. +*/ + +#define pointer_tointeger(p) ((size_t)(p)) // & not allowed on pointer + +#define pointer_aligned32(p) ((pointer_tointeger(p) & 3) == 0) +#define pointer_aligned64(p) ((pointer_tointeger(p) & 7) == 0) + +#define void_data(data) ((void *)(data)) +#define byte_data(data) ((uint8_t *)(data)) + +/* top of the block ghost */ + +#define block_top(block) (byte_data(block + 1)) + +/* where the data begins */ + +#define block_edge8(block) block_top(block) +#define block_edge16(block) block_top(block) +#define block_edge32(block) block_top(block) + +#ifdef BIT32 +# define ALIGN64ON32(block) (pointer_aligned64(block + 1) ? 0 : 4) +# define block_edge64(block) (block_top(block) + ALIGN64ON32(block)) +#else +# define block_edge64(block) block_top(block) +#endif + +#define block_left8(block, size) (size) +#define block_left16(block, size) (size) +#define block_left32(block, size) (size) +#ifdef BIT32 +# define block_left64(block, size) (size - ALIGN64ON32(block)) +#else +# define block_left64(block, size) (size) +#endif + +/* consumed block space; it is important to use edge() macros that involves ALIGN64ON32() */ + +#define block_used8(block) (block->data - block_edge8(block)) +#define block_used16(block) (block->data - block_edge16(block)) +#define block_used32(block) (block->data - block_edge32(block)) +#define block_used64(block) (block->data - block_edge64(block)) + +/* align requested size to keep ream->data / pyre->data always aligned. size is always size_t, no insane overflow checks */ + +#define align_size8(size) ((void)size) +#define align_size16(size) ((void)((size & 1) ? (size += 1) : 0)) +#define align_size32(size) ((void)((size & 3) ? (size += 4 - (size & 3)) : 0)) +#define align_size64(size) ((void)((size & 7) ? (size += 8 - (size & 7)) : 0)) + +/* +done() and pop() operations decrements block->left space by an aligned size; block->left -= alignedwritten. Lets have 8-bytes aligned +variant block. If we tell the user there is 15 bytes left (block->left == 15) and the user taked 12. Aligned is 16, we cannot substract. +We could eventually set block->left to 0, but then pop() operation would no be allowed. Hance, block->left must be aligned. The procedure +is different than for size (size_t), we cannot cross 0xff/0xffff,... bondaries. +*/ + +#define align_space8(space) ((void)space) +#define align_space16(space) ((void)((space & 1) ? (space < 0xFFFF ? (space += 1) : (space -= 1)) : 0)) +#define align_space32(space) ((void)((space & 3) ? (space < 0xFFFFFFFD ? (space += 4 - (space & 3)) : (space -= (space & 3))) : 0)) +#define align_space64(space) ((void)((space & 7) ? (space < 0xFFFFFFFFFFFFFFF8ULL ? (space += 8 - (space & 7)) : (space -= (space & 7))) : 0)) + +/* handling ghost structure (stock and pool) */ + +#if defined(UTIL_MEM_STOCK_H) || defined(UTIL_MEM_POOL_H) + +/* ghost offset from block top; not from bottom because we must not exceed offset limit */ + +#define ghost_offset(block, ghost) (byte_data(ghost) - block_top(block)) + +/* ghost <-> data */ + +#define ghost_data(ghost) ((void *)(ghost + 1)) + +/* cast from data to ghost structure goes via (void *) to shut up warnigns, alignment ok */ + +#define data_ghost8(data) (((ghost8 *)void_data(data)) - 1) +#define data_ghost16(data) (((ghost16 *)void_data(data)) - 1) +#define data_ghost32(data) (((ghost32 *)void_data(data)) - 1) +#define data_ghost64(data) (((ghost64 *)void_data(data)) - 1) + +/* ghost <-> block */ + +#define ghost_block8(ghost, block8) ((block8 *)void_data(byte_data(ghost) - ghost->offset - sizeof(block8))) +#define ghost_block16(ghost, block16) ((block16 *)void_data(byte_data(ghost) - ghost->offset - sizeof(block16))) +#ifdef BIT32 +# define ghost_block32(ghost, block32) (ghost->block) +#else +# define ghost_block32(ghost, block32) ((block32 *)void_data(byte_data(ghost) - ghost->offset - sizeof(block32))) +#endif +#define ghost_block64(ghost, block64) (ghost->block) + +/* ghost init */ + +#define ghost_next8(block, ghost) ((ghost = block->dataghost), (ghost->offset = (uint8_t)ghost_offset(block, ghost))) +#define ghost_next16(block, ghost) ((ghost = block->dataghost), (ghost->offset = (uint16_t)ghost_offset(block, ghost))) +#ifdef BIT32 +# define ghost_next32(bl0ck, ghost) ((ghost = bl0ck->dataghost), (ghost->block = bl0ck)) +#else +# define ghost_next32(block, ghost) ((ghost = block->dataghost), (ghost->offset = (uint32_t)ghost_offset(block, ghost))) +#endif +#define ghost_next64(bl0ck, ghost) ((ghost = bl0ck->dataghost), (ghost->block = bl0ck)) + +#endif + +/* average block chunk size */ + +#define average_block_chunk8(ream) (block_used8(ream) / ream->chunks) +#define average_block_chunk16(ream) (block_used16(ream) / ream->chunks) +#define average_block_chunk32(ream) (block_used32(ream) / ream->chunks) +#define average_block_chunk64(ream) (block_used64(ream) / ream->chunks) + +/* +neglect remaining block tail and start a new block or create a single block; a test for (block->chunks > 0) is a sanity; +if block->chunks is zero (block has a full space left), we shouldn't get there, except when alloc->large is larger then alloc->space +*/ + +#define take_new_block8(alloc, ghoststruct, block, size) \ + ((size < alloc->large) && (block->left <= sizeof(ghoststruct) || (block->chunks > 0 && block->left <= average_block_chunk8(block)))) +#define take_new_block16(alloc, ghoststruct, block, size) \ + ((size < alloc->large) && (block->left <= sizeof(ghoststruct) || (block->chunks > 0 && block->left <= average_block_chunk16(block)))) +#define take_new_block32(alloc, ghoststruct, block, size) \ + ((size < alloc->large) && (block->left <= sizeof(ghoststruct) || (block->chunks > 0 && block->left <= average_block_chunk32(block)))) +#define take_new_block64(alloc, ghoststruct, block, size) \ + ((size < alloc->large) && (block->left <= sizeof(ghoststruct) || (block->chunks > 0 && block->left <= average_block_chunk64(block)))) + +/* empty */ + +#define head_block_empty(alloc, block) (((block = alloc->head) == NULL) || (block->chunks == 0 && block->prev == NULL)) + +#endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemallh.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemallh.h new file mode 100644 index 00000000000..de448ecd51f --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemallh.h @@ -0,0 +1,26 @@ + +#ifndef UTIL_MEM_ALLH_H +#define UTIL_MEM_ALLH_H + +#include <stddef.h> // size_t +#include <stdint.h> + +#include "utildecl.h" + +typedef struct ghost8 ghost8; +typedef struct ghost16 ghost16; +typedef struct ghost32 ghost32; +typedef struct ghost64 ghost64; + +/* info stub */ + +typedef struct { + size_t blocks, singles; + size_t chunks, unused; + size_t used, singleused, left; + size_t ghosts, blockghosts, singleghosts; +} mem_info; + +#define MEM_INFO_INIT() = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + +#endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemheap.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemheap.c new file mode 100644 index 00000000000..9392f698aa0 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemheap.c @@ -0,0 +1,994 @@ + +#include "utilmemheap.h" +#include "utilmemallc.h" + +#define pyre_alloc8(heap, space) ((pyre8 *)((heap->flags & HEAP_ZERO) ? util_calloc(1, sizeof(pyre8) + space * sizeof(uint8_t)) : util_malloc(sizeof(pyre8) + space * sizeof(uint8_t)))) +#define pyre_alloc16(heap, space) ((pyre16 *)((heap->flags & HEAP_ZERO) ? util_calloc(1, sizeof(pyre16) + space * sizeof(uint8_t)) : util_malloc(sizeof(pyre16) + space * sizeof(uint8_t)))) +#define pyre_alloc32(heap, space) ((pyre32 *)((heap->flags & HEAP_ZERO) ? util_calloc(1, sizeof(pyre32) + space * sizeof(uint8_t)) : util_malloc(sizeof(pyre32) + space * sizeof(uint8_t)))) +#define pyre_alloc64(heap, space) ((pyre64 *)((heap->flags & HEAP_ZERO) ? util_calloc(1, sizeof(pyre64) + space * sizeof(uint8_t)) : util_malloc(sizeof(pyre64) + space * sizeof(uint8_t)))) + +#define pyre_free(pyre) util_free(pyre) + +/* block reset */ + +#define reset_heap_head8(heap, pyre, used) \ + ((used = block_used8(pyre)), (pyre->data -= used), ((heap->flags & HEAP_ZERO) ? (memset(pyre->data, 0, used), 0) : 0), (pyre->left += (uint8_t)used)) +#define reset_heap_head16(heap, pyre, used) \ + ((used = block_used16(pyre)), (pyre->data -= used), ((heap->flags & HEAP_ZERO) ? (memset(pyre->data, 0, used), 0) : 0), (pyre->left += (uint16_t)used)) +#define reset_heap_head32(heap, pyre, used) \ + ((used = block_used32(pyre)), (pyre->data -= used), ((heap->flags & HEAP_ZERO) ? (memset(pyre->data, 0, used), 0) : 0), (pyre->left += (uint32_t)used)) +#define reset_heap_head64(heap, pyre, used) \ + ((used = block_used64(pyre)), (pyre->data -= used), ((heap->flags & HEAP_ZERO) ? (memset(pyre->data, 0, used), 0) : 0), (pyre->left += (uint64_t)used)) + +/* init heap */ + +heap8 * heap8_init (heap8 *heap, uint8_t space, uint8_t large, uint8_t flags) +{ + align_space8(space); + if (large > space) large = space; + heap->head = NULL; + heap->space = space; + heap->large = large; + heap->flags = flags; + return heap; +} + +heap16 * heap16_init (heap16 *heap, uint16_t space, uint16_t large, uint8_t flags) +{ + align_space16(space); + if (large > space) large = space; + heap->head = NULL; + heap->space = space; + heap->large = large; + heap->flags = flags; + return heap; +} + +heap32 * heap32_init (heap32 *heap, uint32_t space, uint32_t large, uint8_t flags) +{ + align_space32(space); + if (large > space) large = space; + heap->head = NULL; + heap->space = space; + heap->large = large; + heap->flags = flags; + return heap; +} + +heap64 * heap64_init (heap64 *heap, uint64_t space, uint64_t large, uint8_t flags) +{ + align_space64(space); + if (large > space) large = space; + heap->head = NULL; + heap->space = space; + heap->large = large; + heap->flags = flags; + return heap; +} + +/* free heap */ + +void heap8_free (heap8 *heap) +{ + pyre8 *pyre, *prev; + pyre = heap->head; + heap->head = NULL; + while (pyre != NULL) + { + prev = pyre->prev; + pyre_free(pyre); + pyre = prev; + } +} + +void heap16_free (heap16 *heap) +{ + pyre16 *pyre, *prev; + pyre = heap->head; + heap->head = NULL; + while (pyre != NULL) + { + prev = pyre->prev; + pyre_free(pyre); + pyre = prev; + } +} + +void heap32_free (heap32 *heap) +{ + pyre32 *pyre, *prev; + pyre = heap->head; + heap->head = NULL; + while (pyre != NULL) + { + prev = pyre->prev; + pyre_free(pyre); + pyre = prev; + } +} + +void heap64_free (heap64 *heap) +{ + pyre64 *pyre, *prev; + pyre = heap->head; + heap->head = NULL; + while (pyre != NULL) + { + prev = pyre->prev; + pyre_free(pyre); + pyre = prev; + } +} + +/* clear heap */ + +void heap8_clear (heap8 *heap) +{ + pyre8 *pyre, *prev; + size_t used; + if ((pyre = heap->head) == NULL) + return; + prev = pyre->prev; + pyre->prev = NULL; + reset_heap_head8(heap, pyre, used); + for (; prev != NULL; prev = pyre) + { + pyre = prev->prev; + pyre_free(prev); + } +} + +void heap16_clear (heap16 *heap) +{ + pyre16 *pyre, *prev; + size_t used; + if ((pyre = heap->head) == NULL) + return; + prev = pyre->prev; + pyre->prev = NULL; + reset_heap_head16(heap, pyre, used); + for (; prev != NULL; prev = pyre) + { + pyre = prev->prev; + pyre_free(prev); + } +} + +void heap32_clear (heap32 *heap) +{ + pyre32 *pyre, *prev; + size_t used; + if ((pyre = heap->head) == NULL) + return; + prev = pyre->prev; + pyre->prev = NULL; + reset_heap_head32(heap, pyre, used); + for (; prev != NULL; prev = pyre) + { + pyre = prev->prev; + pyre_free(prev); + } +} + +void heap64_clear (heap64 *heap) +{ + pyre64 *pyre, *prev; + size_t used; + if ((pyre = heap->head) == NULL) + return; + prev = pyre->prev; + pyre->prev = NULL; + reset_heap_head64(heap, pyre, used); + for (; prev != NULL; prev = pyre) + { + pyre = prev->prev; + pyre_free(prev); + } +} + +/* heap head */ + +void heap8_head (heap8 *heap) +{ + pyre8 *pyre; + heap->head = pyre = pyre_alloc8(heap, heap->space); + pyre->prev = NULL; + pyre->data = block_edge8(pyre); + pyre->left = block_left8(pyre, heap->space); + pyre->chunks = 0; +} + +void heap16_head (heap16 *heap) +{ + pyre16 *pyre; + heap->head = pyre = pyre_alloc16(heap, heap->space); + pyre->prev = NULL; + pyre->data = block_edge16(pyre); + pyre->left = block_left16(pyre, heap->space); + pyre->chunks = 0; +} + +void heap32_head (heap32 *heap) +{ + pyre32 *pyre; + heap->head = pyre = pyre_alloc32(heap, heap->space); + pyre->prev = NULL; + pyre->data = block_edge32(pyre); + pyre->left = block_left32(pyre, heap->space); + pyre->chunks = 0; +} + +void heap64_head (heap64 *heap) +{ + pyre64 *pyre; + heap->head = pyre = pyre_alloc64(heap, heap->space); + pyre->prev = NULL; + pyre->data = block_edge64(pyre); + pyre->left = block_left64(pyre, heap->space); + pyre->chunks = 0; +} + +/* next heap head */ + +static pyre8 * heap8_new (heap8 *heap) +{ + pyre8 *pyre; + pyre = pyre_alloc8(heap, heap->space); + pyre->prev = heap->head; + heap->head = pyre; + pyre->data = block_edge8(pyre); + pyre->left = block_left8(pyre, heap->space); + pyre->chunks = 0; + return pyre; +} + +static pyre16 * heap16_new (heap16 *heap) +{ + pyre16 *pyre; + pyre = pyre_alloc16(heap, heap->space); + pyre->prev = heap->head; + heap->head = pyre; + pyre->data = block_edge16(pyre); + pyre->left = block_left16(pyre, heap->space); + pyre->chunks = 0; + return pyre; +} + +static pyre32 * heap32_new (heap32 *heap) +{ + pyre32 *pyre; + pyre = pyre_alloc32(heap, heap->space); + pyre->prev = heap->head; + heap->head = pyre; + pyre->data = block_edge32(pyre); + pyre->left = block_left32(pyre, heap->space); + pyre->chunks = 0; + return pyre; +} + +static pyre64 * heap64_new (heap64 *heap) +{ + pyre64 *pyre; + pyre = pyre_alloc64(heap, heap->space); + pyre->prev = heap->head; + heap->head = pyre; + pyre->data = block_edge64(pyre); + pyre->left = block_left64(pyre, heap->space); + pyre->chunks = 0; + return pyre; +} + +/* next heap sole */ + +static pyre8 * heap8_sole (heap8 *heap, size_t size) +{ + pyre8 *pyre, *head, *prev; + pyre = pyre_alloc8(heap, size); + head = heap->head; + prev = head->prev; + pyre->prev = prev; + head->prev = pyre; + pyre->data = block_edge8(pyre); + pyre->left = 0; // (uint8_t)size makes no sense, even with buffer api it will finally become 0 + return pyre; +} + +static pyre16 * heap16_sole (heap16 *heap, size_t size) +{ + pyre16 *pyre, *head, *prev; + pyre = pyre_alloc16(heap, size); + head = heap->head; + prev = head->prev; + pyre->prev = prev; + head->prev = pyre; + pyre->data = block_edge16(pyre); + pyre->left = 0; + return pyre; +} + +static pyre32 * heap32_sole (heap32 *heap, size_t size) +{ + pyre32 *pyre, *head, *prev; + pyre = pyre_alloc32(heap, size); + head = heap->head; + prev = head->prev; + pyre->prev = prev; + head->prev = pyre; + pyre->data = block_edge32(pyre); + pyre->left = 0; + return pyre; +} + +static pyre64 * heap64_sole (heap64 *heap, size_t size) +{ + pyre64 *pyre, *head, *prev; + pyre = pyre_alloc64(heap, size); + head = heap->head; + prev = head->prev; + pyre->prev = prev; + head->prev = pyre; + pyre->data = block_edge64(pyre); + pyre->left = 0; + return pyre; +} + +/* take from heap */ + +#define pyre_next8(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->left -= (uint8_t)size, ++pyre->chunks) +#define pyre_next16(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->left -= (uint16_t)size, ++pyre->chunks) +#define pyre_next32(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->left -= (uint32_t)size, ++pyre->chunks) +#define pyre_next64(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->left -= (uint64_t)size, ++pyre->chunks) + +// for sole blocks, block->left is permanently 0, we can't store size_t there +#define pyre_last8(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->chunks = 1) +#define pyre_last16(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->chunks = 1) +#define pyre_last32(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->chunks = 1) +#define pyre_last64(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->chunks = 1) + +void * _heap8_take (heap8 *heap, size_t size) +{ + pyre8 *pyre; + void *data; + pyre = heap->head; + align_size8(size); + if (size <= pyre->left) + { + pyre_next8(data, pyre, size); + } + else if (take_new_block8(heap, pyre8, pyre, size)) + { + pyre = heap8_new(heap); + pyre_next8(data, pyre, size); + } + else + { + pyre = heap8_sole(heap, size); + pyre_last8(data, pyre, size); + } + return data; +} + +void * _heap16_take (heap16 *heap, size_t size) +{ + pyre16 *pyre; + void *data; + pyre = heap->head; + align_size16(size); + if (size <= pyre->left) + { + pyre_next16(data, pyre, size); + } + else if (take_new_block16(heap, pyre16, pyre, size)) + { + pyre = heap16_new(heap); + pyre_next16(data, pyre, size); + } + else + { + pyre = heap16_sole(heap, size); + pyre_last16(data, pyre, size); + } + return data; +} + +void * _heap32_take (heap32 *heap, size_t size) +{ + pyre32 *pyre; + void *data; + pyre = heap->head; + align_size32(size); + if (size <= pyre->left) + { + pyre_next32(data, pyre, size); + } + else if (take_new_block32(heap, pyre32, pyre, size)) + { + pyre = heap32_new(heap); + pyre_next32(data, pyre, size); + } + else + { + pyre = heap32_sole(heap, size); + pyre_last32(data, pyre, size); + } + return data; +} + +void * _heap64_take (heap64 *heap, size_t size) +{ + pyre64 *pyre; + void *data; + pyre = heap->head; + align_size64(size); + if (size <= pyre->left) + { + pyre_next64(data, pyre, size); + } + else if (take_new_block64(heap, pyre64, pyre, size)) + { + pyre = heap64_new(heap); + pyre_next64(data, pyre, size); + } + else + { + pyre = heap64_sole(heap, size); + pyre_last64(data, pyre, size); + } + return data; +} + +/* pop last heap chunk */ + +#define taken_from_head(taken, head) (byte_data(taken) == head->data) +#define taken_from_sole(taken, head, sole) ((sole = head->prev) != NULL && byte_data(taken) == sole->data) + +#define taken_prev_head(taken, head, size) (byte_data(taken) == head->data - size) +#define taken_prev_sole(taken, head, sole, size) ((sole = head->prev) != NULL && byte_data(taken) == sole->data - size) + +void heap8_pop (heap8 *heap, void *taken, size_t size) +{ + pyre8 *pyre, *head; + head = heap->head; + align_size8(size); + if (taken_prev_head(taken, head, size)) + { + + head->data -= size; + head->left += (uint8_t)size; + --head->chunks; + } + else if (taken_prev_sole(taken, head, pyre, size)) + { + head->prev = pyre->prev; + pyre_free(pyre); + } +} + +void heap16_pop (heap16 *heap, void *taken, size_t size) +{ + pyre16 *pyre, *head; + head = heap->head; + align_size16(size); + if (taken_prev_head(taken, head, size)) + { + + head->data -= size; + head->left += (uint16_t)size; + --head->chunks; + } + else if (taken_prev_sole(taken, head, pyre, size)) + { + head->prev = pyre->prev; + pyre_free(pyre); + } +} + +void heap32_pop (heap32 *heap, void *taken, size_t size) +{ + pyre32 *pyre, *head; + head = heap->head; + align_size32(size); + if (taken_prev_head(taken, head, size)) + { + + head->data -= size; + head->left += (uint32_t)size; + --head->chunks; + } + else if (taken_prev_sole(taken, head, pyre, size)) + { + head->prev = pyre->prev; + pyre_free(pyre); + } +} + +void heap64_pop (heap64 *heap, void *taken, size_t size) +{ + pyre64 *pyre, *head; + head = heap->head; + align_size64(size); + if (taken_prev_head(taken, head, size)) + { + + head->data -= size; + head->left += (uint64_t)size; + --head->chunks; + } + else if (taken_prev_sole(taken, head, pyre, size)) + { + head->prev = pyre->prev; + pyre_free(pyre); + } +} + +/* heap buffer */ + +void * _heap8_some (heap8 *heap, size_t size, size_t *pspace) +{ + pyre8 *pyre; + pyre = heap->head; + align_size8(size); + if (size <= pyre->left) + { + *pspace = pyre->left; + } + else if (take_new_block8(heap, pyre8, pyre, size)) + { + pyre = heap8_new(heap); + *pspace = pyre->left; + } + else + { + pyre = heap8_sole(heap, size); + *pspace = size; + } + return void_data(pyre->data); +} + +void * _heap16_some (heap16 *heap, size_t size, size_t *pspace) +{ + pyre16 *pyre; + pyre = heap->head; + align_size16(size); + if (size <= pyre->left) + { + *pspace = pyre->left; + } + else if (take_new_block16(heap, pyre16, pyre, size)) + { + pyre = heap16_new(heap); + *pspace = pyre->left; + } + else + { + pyre = heap16_sole(heap, size); + *pspace = size; + } + return void_data(pyre->data); +} + +void * _heap32_some (heap32 *heap, size_t size, size_t *pspace) +{ + pyre32 *pyre; + pyre = heap->head; + align_size32(size); + if (size <= pyre->left) + { + *pspace = pyre->left; + } + else if (take_new_block32(heap, pyre32, pyre, size)) + { + pyre = heap32_new(heap); + *pspace = pyre->left; + } + else + { + pyre = heap32_sole(heap, size); + *pspace = size; + } + return void_data(pyre->data); +} + +void * _heap64_some (heap64 *heap, size_t size, size_t *pspace) +{ + pyre64 *pyre; + pyre = heap->head; + align_size64(size); + if (size <= pyre->left) + { + *pspace = pyre->left; + } + else if (take_new_block64(heap, pyre64, pyre, size)) + { + pyre = heap64_new(heap); + *pspace = pyre->left; + } + else + { + pyre = heap64_sole(heap, size); + *pspace = size; + } + return void_data(pyre->data); +} + +void * heap8_more (heap8 *heap, void *taken, size_t written, size_t size) +{ + pyre8 *pyre, *prev; + pyre = heap->head; + align_size8(size); + if (taken_from_head(taken, pyre)) + { + if (size <= pyre->left) + { // unlikely + } + else if (take_new_block8(heap, pyre8, pyre, size)) + { + pyre = heap8_new(heap); + memcpy(pyre->data, taken, written); + } + else + { + pyre = heap8_sole(heap, size); + memcpy(pyre->data, taken, written); + } + } + else if (taken_from_sole(taken, pyre, prev)) + { + pyre = heap8_sole(heap, size); + pyre->prev = prev->prev; + memcpy(pyre->data, taken, written); + pyre_free(prev); + } + else + return NULL; + return void_data(pyre->data); +} + +void * heap16_more (heap16 *heap, void *taken, size_t written, size_t size) +{ + pyre16 *pyre, *prev; + pyre = heap->head; + align_size16(size); + if (taken_from_head(taken, pyre)) + { + if (size <= pyre->left) + { + } + else if (take_new_block16(heap, pyre16, pyre, size)) + { + pyre = heap16_new(heap); + memcpy(pyre->data, taken, written); + } + else + { + pyre = heap16_sole(heap, size); + memcpy(pyre->data, taken, written); + } + } + else if (taken_from_sole(taken, pyre, prev)) + { + pyre = heap16_sole(heap, size); + pyre->prev = prev->prev; + memcpy(pyre->data, taken, written); + pyre_free(prev); + } + else + return NULL; + return void_data(pyre->data); +} + +void * heap32_more (heap32 *heap, void *taken, size_t written, size_t size) +{ + pyre32 *pyre, *prev; + pyre = heap->head; + align_size32(size); + if (taken_from_head(taken, pyre)) + { + if (size <= pyre->left) + { + } + else if (take_new_block32(heap, pyre32, pyre, size)) + { + pyre = heap32_new(heap); + memcpy(pyre->data, taken, written); + } + else + { + pyre = heap32_sole(heap, size); + memcpy(pyre->data, taken, written); + } + } + else if (taken_from_sole(taken, pyre, prev)) + { + pyre = heap32_sole(heap, size); + pyre->prev = prev->prev; + memcpy(pyre->data, taken, written); + pyre_free(prev); + } + else + return NULL; + return void_data(pyre->data); +} + +void * heap64_more (heap64 *heap, void *taken, size_t written, size_t size) +{ + pyre64 *pyre, *prev; + pyre = heap->head; + align_size64(size); + if (taken_from_head(taken, pyre)) + { + if (size <= pyre->left) + { + } + else if (take_new_block64(heap, pyre64, pyre, size)) + { + pyre = heap64_new(heap); + memcpy(pyre->data, taken, written); + } + else + { + pyre = heap64_sole(heap, size); + memcpy(pyre->data, taken, written); + } + } + else if (taken_from_sole(taken, pyre, prev)) + { + pyre = heap64_sole(heap, size); + pyre->prev = prev->prev; + memcpy(pyre->data, taken, written); + pyre_free(prev); + } + else + return NULL; + return void_data(pyre->data); +} + +void heap8_done (heap8 *heap, void *taken, size_t written) +{ + pyre8 *pyre; + pyre = heap->head; + align_size8(written); + if (taken_from_head(taken, pyre)) + { + pyre->data += written; + pyre->left -= (uint8_t)written; + ++pyre->chunks; + } + else if (taken_from_sole(taken, pyre, pyre)) + { + pyre->data += written; + pyre->chunks = 1; + } +} + +void heap16_done (heap16 *heap, void *taken, size_t written) +{ + pyre16 *pyre; + pyre = heap->head; + align_size16(written); + if (taken_from_head(taken, pyre)) + { + pyre->data += written; + pyre->left -= (uint16_t)written; + ++pyre->chunks; + } + else if (taken_from_sole(taken, pyre, pyre)) + { + pyre->data += written; + pyre->chunks = 1; + } +} + +void heap32_done (heap32 *heap, void *taken, size_t written) +{ + pyre32 *pyre; + pyre = heap->head; + align_size32(written); + if (taken_from_head(taken, pyre)) + { + pyre->data += written; + pyre->left -= (uint32_t)written; + ++pyre->chunks; + } + else if (taken_from_sole(taken, pyre, pyre)) + { + pyre->data += written; + pyre->chunks = 1; + } +} + +void heap64_done (heap64 *heap, void *taken, size_t written) +{ + pyre64 *pyre; + pyre = heap->head; + align_size64(written); + if (taken_from_head(taken, pyre)) + { + pyre->data += written; + pyre->left -= (uint64_t)written; + ++pyre->chunks; + } + else if (taken_from_sole(taken, pyre, pyre)) + { + pyre->data += written; + pyre->chunks = 1; + } +} + +/* giveup */ + +void heap8_giveup (heap8 *heap, void *taken) +{ + pyre8 *head, *pyre; + head = heap->head; + if (taken_from_sole(taken, head, pyre)) + { + head->prev = pyre->prev; + pyre_free(pyre); + } +} + +void heap16_giveup (heap16 *heap, void *taken) +{ + pyre16 *head, *pyre; + head = heap->head; + if (taken_from_sole(taken, head, pyre)) + { + head->prev = pyre->prev; + pyre_free(pyre); + } +} + +void heap32_giveup (heap32 *heap, void *taken) +{ + pyre32 *head, *pyre; + head = heap->head; + if (taken_from_sole(taken, head, pyre)) + { + head->prev = pyre->prev; + pyre_free(pyre); + } +} + +void heap64_giveup (heap64 *heap, void *taken) +{ + pyre64 *head, *pyre; + head = heap->head; + if (taken_from_sole(taken, head, pyre)) + { + head->prev = pyre->prev; + pyre_free(pyre); + } +} + +/* heap empty */ + +int heap8_empty (heap8 *heap) +{ + pyre8 *pyre; + return head_block_empty(heap, pyre); +} + +int heap16_empty (heap16 *heap) +{ + pyre16 *pyre; + return head_block_empty(heap, pyre); +} + +int heap32_empty (heap32 *heap) +{ + pyre32 *pyre; + return head_block_empty(heap, pyre); +} + +int heap64_empty (heap64 *heap) +{ + pyre64 *pyre; + return head_block_empty(heap, pyre); +} + +/* heap stats */ + +void heap8_stats (heap8 *heap, mem_info *info, int append) +{ + pyre8 *pyre; + size_t used, chunks = 0, blocks = 0, singles = 0; + if (!append) + memset(info, 0, sizeof(mem_info)); + for (pyre = heap->head; pyre != NULL; pyre = pyre->prev) + { + ++blocks; + chunks += pyre->chunks; + used = block_used8(pyre); + info->used += used; + info->left += pyre->left; + if (pyre->chunks == 1 && pyre->left == 0) + { + ++singles; + info->singleused += used; + } + } + info->chunks += chunks; + info->blocks += blocks; + info->blockghosts += blocks * sizeof(pyre8); + info->singles += singles; + info->singleghosts += singles * sizeof(pyre8); +} + +void heap16_stats (heap16 *heap, mem_info *info, int append) +{ + pyre16 *pyre; + size_t used, chunks = 0, blocks = 0, singles = 0; + if (!append) + memset(info, 0, sizeof(mem_info)); + for (pyre = heap->head; pyre != NULL; pyre = pyre->prev) + { + ++blocks; + chunks += pyre->chunks; + used = block_used16(pyre); + info->used += used; + info->left += pyre->left; + if (pyre->chunks == 1 && pyre->left == 0) + { + ++singles; + info->singleused += used; + } + } + info->chunks += chunks; + info->blocks += blocks; + info->blockghosts += blocks * sizeof(pyre16); + info->singles += singles; + info->singleghosts += singles * sizeof(pyre16); +} + +void heap32_stats (heap32 *heap, mem_info *info, int append) +{ + pyre32 *pyre; + size_t used, chunks = 0, blocks = 0, singles = 0; + if (!append) + memset(info, 0, sizeof(mem_info)); + for (pyre = heap->head; pyre != NULL; pyre = pyre->prev) + { + ++blocks; + chunks += pyre->chunks; + used = block_used32(pyre); + info->used += used; + info->left += pyre->left; + if (pyre->chunks == 1 && pyre->left == 0) + { + ++singles; + info->singleused += used; + } + } + info->chunks += chunks; + info->blocks += blocks; + info->blockghosts += blocks * sizeof(pyre32); + info->singles += singles; + info->singleghosts += singles * sizeof(pyre32); +} + +void heap64_stats (heap64 *heap, mem_info *info, int append) +{ + pyre64 *pyre; + size_t used, chunks = 0, blocks = 0, singles = 0; + if (!append) + memset(info, 0, sizeof(mem_info)); + for (pyre = heap->head; pyre != NULL; pyre = pyre->prev) + { + ++blocks; + chunks += pyre->chunks; + used = block_used64(pyre); + info->used += used; + info->left += pyre->left; + if (pyre->chunks == 1 && pyre->left == 0) + { + ++singles; + info->singleused += used; + } + } + info->chunks += chunks; + info->blocks += blocks; + info->blockghosts += blocks * sizeof(pyre64); + info->singles += singles; + info->singleghosts += singles * sizeof(pyre64); +} diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemheap.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemheap.h new file mode 100644 index 00000000000..08f1ce23270 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemheap.h @@ -0,0 +1,179 @@ + +#ifndef UTIL_MEM_HEAP_H +#define UTIL_MEM_HEAP_H + +#include "utilmemallh.h" + +typedef struct pyre8 pyre8; +typedef struct pyre16 pyre16; +typedef struct pyre32 pyre32; +typedef struct pyre64 pyre64; + +struct pyre8 { + pyre8 *prev; + uint8_t *data; + uint8_t left; + uint8_t chunks; +#ifdef BIT32 + uint8_t dummy[2]; // 10->12 +#else + uint8_t dummy[6]; // 18->24 +#endif +}; + +struct pyre16 { + pyre16 *prev; + uint8_t *data; + uint16_t left; + uint16_t chunks; +#ifdef BIT32 + //uint8_t dummy[0]; // 12->12 +#else + uint8_t dummy[4]; // 20->24 +#endif +}; + +struct pyre32 { + pyre32 *prev; + uint8_t *data; + uint32_t left; + uint32_t chunks; +#ifdef BIT32 + //uint8_t dummy[0]; // 16->16 +#else + //uint8_t dummy[0]; // 24->24 +#endif +}; + +struct pyre64 { + pyre64 *prev; + uint8_t *data; + uint64_t left; + uint64_t chunks; +#ifdef BIT32 + //uint8_t dummy[0]; // 24->24 +#else + //uint8_t dummy[0]; // 32->32 +#endif +}; + +/* heaps */ + +typedef struct heap8 heap8; +typedef struct heap16 heap16; +typedef struct heap32 heap32; +typedef struct heap64 heap64; + +struct heap8 { + pyre8 *head; + uint8_t space; + uint8_t large; + uint8_t flags; +}; + +struct heap16 { + pyre16 *head; + uint16_t space; + uint16_t large; + uint8_t flags; +}; + +struct heap32 { + pyre32 *head; + uint32_t space; + uint32_t large; + uint8_t flags; +}; + +struct heap64 { + pyre64 *head; + uint64_t space; + uint64_t large; + uint8_t flags; +}; + +#define HEAP_ZERO (1 << 0) +//#define HEAP_KEEP (1 << 1) +#define HEAP_DEFAULTS 0 + +#define HEAP8_INIT(space, large, flags) { NULL, space, large, flags } +#define HEAP16_INIT(space, large, flags) { NULL, space, large, flags } +#define HEAP32_INIT(space, large, flags) { NULL, space, large, flags } +#define HEAP64_INIT(space, large, flags) { NULL, space, large, flags } + +UTILAPI heap8 * heap8_init (heap8 *heap, uint8_t space, uint8_t large, uint8_t flags); +UTILAPI heap16 * heap16_init (heap16 *heap, uint16_t space, uint16_t large, uint8_t flags); +UTILAPI heap32 * heap32_init (heap32 *heap, uint32_t space, uint32_t large, uint8_t flags); +UTILAPI heap64 * heap64_init (heap64 *heap, uint64_t space, uint64_t large, uint8_t flags); + +UTILAPI void heap8_head (heap8 *heap); +UTILAPI void heap16_head (heap16 *heap); +UTILAPI void heap32_head (heap32 *heap); +UTILAPI void heap64_head (heap64 *heap); + +#define heap8_ensure_head(heap) ((void)((heap)->head != NULL || (heap8_head(heap), 0))) +#define heap16_ensure_head(heap) ((void)((heap)->head != NULL || (heap16_head(heap), 0))) +#define heap32_ensure_head(heap) ((void)((heap)->head != NULL || (heap32_head(heap), 0))) +#define heap64_ensure_head(heap) ((void)((heap)->head != NULL || (heap64_head(heap), 0))) + +UTILAPI void heap8_free (heap8 *heap); +UTILAPI void heap16_free (heap16 *heap); +UTILAPI void heap32_free (heap32 *heap); +UTILAPI void heap64_free (heap64 *heap); + +UTILAPI void heap8_clear (heap8 *heap); +UTILAPI void heap16_clear (heap16 *heap); +UTILAPI void heap32_clear (heap32 *heap); +UTILAPI void heap64_clear (heap64 *heap); + +UTILAPI void * _heap8_take (heap8 *heap, size_t size); +UTILAPI void * _heap16_take (heap16 *heap, size_t size); +UTILAPI void * _heap32_take (heap32 *heap, size_t size); +UTILAPI void * _heap64_take (heap64 *heap, size_t size); + +#define heap8_take(heap, size) (heap8_ensure_head(heap), _heap8_take(heap, size)) +#define heap16_take(heap, size) (heap16_ensure_head(heap), _heap16_take(heap, size)) +#define heap32_take(heap, size) (heap32_ensure_head(heap), _heap32_take(heap, size)) +#define heap64_take(heap, size) (heap64_ensure_head(heap), _heap64_take(heap, size)) + +UTILAPI void heap8_pop (heap8 *heap, void *taken, size_t size); +UTILAPI void heap16_pop (heap16 *heap, void *taken, size_t size); +UTILAPI void heap32_pop (heap32 *heap, void *taken, size_t size); +UTILAPI void heap64_pop (heap64 *heap, void *taken, size_t size); + +UTILAPI void * _heap8_some (heap8 *heap, size_t size, size_t *pspace); +UTILAPI void * _heap16_some (heap16 *heap, size_t size, size_t *pspace); +UTILAPI void * _heap32_some (heap32 *heap, size_t size, size_t *pspace); +UTILAPI void * _heap64_some (heap64 *heap, size_t size, size_t *pspace); + +#define heap8_some(heap, size, pspace) (heap8_ensure_head(heap), _heap8_some(heap, size, pspace)) +#define heap16_some(heap, size, pspace) (heap16_ensure_head(heap), _heap16_some(heap, size, pspace)) +#define heap32_some(heap, size, pspace) (heap32_ensure_head(heap), _heap32_some(heap, size, pspace)) +#define heap64_some(heap, size, pspace) (heap64_ensure_head(heap), _heap64_some(heap, size, pspace)) + +UTILAPI void * heap8_more (heap8 *heap, void *taken, size_t written, size_t size); +UTILAPI void * heap16_more (heap16 *heap, void *taken, size_t written, size_t size); +UTILAPI void * heap32_more (heap32 *heap, void *taken, size_t written, size_t size); +UTILAPI void * heap64_more (heap64 *heap, void *taken, size_t written, size_t size); + +UTILAPI void heap8_done (heap8 *heap, void *taken, size_t written); +UTILAPI void heap16_done (heap16 *heap, void *taken, size_t written); +UTILAPI void heap32_done (heap32 *heap, void *taken, size_t written); +UTILAPI void heap64_done (heap64 *heap, void *taken, size_t written); + +UTILAPI void heap8_giveup (heap8 *heap, void *taken); +UTILAPI void heap16_giveup (heap16 *heap, void *taken); +UTILAPI void heap32_giveup (heap32 *heap, void *taken); +UTILAPI void heap64_giveup (heap64 *heap, void *taken); + +UTILAPI int heap8_empty (heap8 *heap); +UTILAPI int heap16_empty (heap16 *heap); +UTILAPI int heap32_empty (heap32 *heap); +UTILAPI int heap64_empty (heap64 *heap); + +UTILAPI void heap8_stats (heap8 *heap, mem_info *info, int append); +UTILAPI void heap16_stats (heap16 *heap, mem_info *info, int append); +UTILAPI void heap32_stats (heap32 *heap, mem_info *info, int append); +UTILAPI void heap64_stats (heap64 *heap, mem_info *info, int append); + +#endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemheapiof.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemheapiof.c new file mode 100644 index 00000000000..f459780df3e --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemheapiof.c @@ -0,0 +1,192 @@ + +#include "utilmemheapiof.h" + +// this is identical to stock iof suite, keep in sync + +static size_t heap8_writer (iof *O, iof_mode mode) +{ + heap8 *heap; + size_t written; + heap = (heap8 *)O->link; + switch (mode) + { + case IOFFLUSH: + written = (size_t)iof_size(O); + heap8_done(heap, O->buf, written); + O->buf = _heap8_some(heap, 0, &O->space); + O->pos = O->buf; + O->end = O->buf + O->space; + break; + case IOFWRITE: + written = (size_t)iof_size(O); + O->space = written << 1; + O->buf = heap8_more(heap, O->buf, written, O->space); + O->pos = O->buf + written; + O->end = O->buf + O->space; + return written; // eq (space - written) + case IOFCLOSE: + default: + break; + } + return 0; +} + +static size_t heap16_writer (iof *O, iof_mode mode) +{ + heap16 *heap; + size_t written; + heap = (heap16 *)O->link; + switch (mode) + { + case IOFFLUSH: + written = (size_t)iof_size(O); + heap16_done(heap, O->buf, written); + O->buf = _heap16_some(heap, 0, &O->space); + O->pos = O->buf; + O->end = O->buf + O->space; + break; + case IOFWRITE: + written = (size_t)iof_size(O); + O->space = written << 1; + O->buf = heap16_more(heap, O->buf, written, O->space); + O->pos = O->buf + written; + O->end = O->buf + O->space; + return written; // eq (space - written) + case IOFCLOSE: + default: + break; + } + return 0; +} + +static size_t heap32_writer (iof *O, iof_mode mode) +{ + heap32 *heap; + size_t written; + heap = (heap32 *)O->link; + switch (mode) + { + case IOFFLUSH: + written = (size_t)iof_size(O); + heap32_done(heap, O->buf, written); + O->buf = _heap32_some(heap, 0, &O->space); + O->pos = O->buf; + O->end = O->buf + O->space; + break; + case IOFWRITE: + written = (size_t)iof_size(O); + O->space = written << 1; + O->buf = heap32_more(heap, O->buf, written, O->space); + O->pos = O->buf + written; + O->end = O->buf + O->space; + return written; // eq (space - written) + case IOFCLOSE: + default: + break; + } + return 0; +} + +static size_t heap64_writer (iof *O, iof_mode mode) +{ + heap64 *heap; + size_t written; + heap = (heap64 *)O->link; + switch (mode) + { + case IOFFLUSH: + written = (size_t)iof_size(O); + heap64_done(heap, O->buf, written); + O->buf = _heap64_some(heap, 0, &O->space); + O->pos = O->buf; + O->end = O->buf + O->space; + break; + case IOFWRITE: + written = (size_t)iof_size(O); + O->space = written << 1; + O->buf = heap64_more(heap, O->buf, written, O->space); + O->pos = O->buf + written; + O->end = O->buf + O->space; + return written; // eq (space - written) + case IOFCLOSE: + default: + break; + } + return 0; +} + +/* buffer init (made once) */ + +iof * heap8_buffer_init (heap8 *heap, iof *O) +{ + void *data; + size_t space; + data = heap8_some(heap, 0, &space); + if (iof_writer(O, (void *)heap, heap8_writer, data, space) == NULL) // sanity + return NULL; + return O; +} + +iof * heap16_buffer_init (heap16 *heap, iof *O) +{ + void *data; + size_t space; + data = heap16_some(heap, 0, &space); + if (iof_writer(O, (void *)heap, heap16_writer, data, space) == NULL) + return NULL; + return O; +} + +iof * heap32_buffer_init (heap32 *heap, iof *O) +{ + void *data; + size_t space; + data = heap32_some(heap, 0, &space); + if (iof_writer(O, (void *)heap, heap32_writer, data, space) == NULL) + return NULL; + return O; +} + +iof * heap64_buffer_init (heap64 *heap, iof *O) +{ + void *data; + size_t space; + data = heap64_some(heap, 0, &space); + if (iof_writer(O, (void *)heap, heap64_writer, data, space) == NULL) + return NULL; + return O; +} + +/* buffer for some */ + +iof * heap8_buffer_some (heap8 *heap, iof *O, size_t atleast) +{ + O->buf = _heap8_some(heap, atleast, &O->space); + O->pos = O->buf; + O->end = O->buf + O->space; + return O; +} + +iof * heap16_buffer_some (heap16 *heap, iof *O, size_t atleast) +{ + O->buf = _heap16_some(heap, atleast, &O->space); + O->pos = O->buf; + O->end = O->buf + O->space; + return O; +} + +iof * heap32_buffer_some (heap32 *heap, iof *O, size_t atleast) +{ + O->buf = _heap32_some(heap, atleast, &O->space); + O->pos = O->buf; + O->end = O->buf + O->space; + return O; +} + +iof * heap64_buffer_some (heap64 *heap, iof *O, size_t atleast) +{ + O->buf = _heap64_some(heap, atleast, &O->space); + O->pos = O->buf; + O->end = O->buf + O->space; + return O; +} diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemheapiof.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemheapiof.h new file mode 100644 index 00000000000..8384eda7aeb --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmemheapiof.h @@ -0,0 +1,18 @@ + +#ifndef UTIL_MEM_HEAP_IOF_H +#define UTIL_MEM_HEAP_IOF_H + +#include "utilmemheap.h" +#include "utiliof.h" + +UTILAPI iof * heap8_buffer_init (heap8 *heap, iof *O); +UTILAPI iof * heap16_buffer_init (heap16 *heap, iof *O); +UTILAPI iof * heap32_buffer_init (heap32 *heap, iof *O); +UTILAPI iof * heap64_buffer_init (heap64 *heap, iof *O); + +UTILAPI iof * heap8_buffer_some (heap8 *heap, iof *O, size_t atleast); +UTILAPI iof * heap16_buffer_some (heap16 *heap, iof *O, size_t atleast); +UTILAPI iof * heap32_buffer_some (heap32 *heap, iof *O, size_t atleast); +UTILAPI iof * heap64_buffer_some (heap64 *heap, iof *O, size_t atleast); + +#endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmeminfo.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmeminfo.c new file mode 100644 index 00000000000..d3f61d5cac9 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmeminfo.c @@ -0,0 +1,38 @@ +/* print stats; common for heap, stock and pool */ + +#include <stdio.h> + +#include "utilmeminfo.h" + +#define UINT(i) ((unsigned long)(i)) + +void show_mem_info (mem_info *info) +{ + size_t totalwaste, totalmem, averagechunk, singlemem; + double ftotalwaste, fblockwaste, fghostwaste, ftailwaste, fsinglewaste; + double funused, fsingles, fsinglemem, fsingleeff; + + totalwaste = info->ghosts + info->blockghosts + info->left; + totalmem = info->used + totalwaste; + + ftotalwaste = totalmem > 0 ? totalwaste * 100.0 / totalmem : 0; + fblockwaste = totalmem > 0 ? (info->blockghosts - info->singleghosts) * 100.0 / totalmem : 0; + fsinglewaste = totalmem > 0 ? info->singleghosts * 100.0 / totalmem : 0; + fghostwaste = totalmem > 0 ? info->ghosts * 100.0 / totalmem : 0; + ftailwaste = totalmem > 0 ? info->left * 100.0 / totalmem : 0; + + averagechunk = info->chunks > 0 ? info->used / info->chunks : 0; + funused = info->chunks > 0 ? info->unused * 100.0 / info->chunks : 0.0; + + fsingles = info->blocks > 0 ? info->singles * 100.0 / info->blocks : 0; + fsinglemem = info->used > 0 ? info->singleused * 100.0 / info->used : 0; + singlemem = info->singleused + info->singleghosts; + fsingleeff = singlemem > 0 ? info->singleused * 100.0 / singlemem : 0; + + printf("total: %lu + %lu = %lu\n", UINT(info->used), UINT(totalwaste), UINT(totalmem)); + printf("chunks: %lu of average size %lu, unused %lu[%.2f%%]\n", UINT(info->chunks), UINT(averagechunk), UINT(info->unused), funused); + printf("blocks: %lu, singles %lu[%.2f%%], %.2f%% of allocs, efficiency %.2f%%\n", + UINT(info->blocks), UINT(info->singles), fsingles, fsinglemem, fsingleeff); + printf("waste: %lu[%0.2f%%], block ghosts %0.2f%%, single ghosts %.2f%%, chunk ghosts %0.2f%%, tails %0.2f%%\n\n", + UINT(totalwaste), ftotalwaste, fblockwaste, fsinglewaste, fghostwaste, ftailwaste); +} diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmeminfo.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmeminfo.h new file mode 100644 index 00000000000..cfa0fd670ac --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilmeminfo.h @@ -0,0 +1,9 @@ + +#ifndef UTIL_MEM_INFO_H +#define UTIL_MEM_INFO_H + +#include "utilmemallh.h" + +UTILAPI void show_mem_info (mem_info *info); + +#endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilnumber.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilnumber.c index c87261e15ab..4352c26fbd0 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilnumber.c +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilnumber.c @@ -4,6 +4,10 @@ #include "utilnumber.h" +// todo: lookups can be chars +// change lookup arrays to some __name to discourage accessing them directly; they always should be accessed via macros; base16_value() base16_digit() +// + const int base10_lookup[] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, @@ -80,6 +84,10 @@ const int base36_lookup[] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; +/* common buffer for quick conversions (unsafe) */ + +char util_number_buffer[NUMBER_BUFFER_SIZE] = { 0 }; + /* integer from string; return a pointer to character next to the last digit */ #define string_scan_sign(s, c, sign) _scan_sign(c, sign, *++s) @@ -97,7 +105,7 @@ const char * string_to_int32 (const char *s, int32_t *number) return s; } -const char * string_to_intlw (const char *s, intlw_t *number) +const char * string_to_slong (const char *s, long *number) { int sign, c = *s; string_scan_sign(s, c, sign); @@ -122,7 +130,14 @@ const char * string_to_uint32 (const char *s, uint32_t *number) return s; } -const char * string_to_uintlw (const char *s, uintlw_t *number) +const char * string_to_ulong (const char *s, unsigned long *number) +{ + int c = *s; + string_scan_integer(s, c, *number); + return s; +} + +const char * string_to_usize (const char *s, size_t *number) { int c = *s; string_scan_integer(s, c, *number); @@ -145,7 +160,7 @@ const char * radix_to_int32 (const char *s, int32_t *number, int radix) return s; } -const char * radix_to_intlw (const char *s, intlw_t *number, int radix) +const char * radix_to_slong (const char *s, long *number, int radix) { int sign, c = *s; string_scan_sign(s, c, sign); @@ -170,7 +185,14 @@ const char * radix_to_uint32 (const char *s, uint32_t *number, int radix) return s; } -const char * radix_to_uintlw (const char *s, uintlw_t *number, int radix) +const char * radix_to_ulong (const char *s, unsigned long *number, int radix) +{ + int c = *s; + string_scan_radix(s, c, *number, radix); + return s; +} + +const char * radix_to_usize (const char *s, size_t *number, int radix) { int c = *s; string_scan_radix(s, c, *number, radix); @@ -274,10 +296,7 @@ const char * roman_to_uint16 (const char *s, uint16_t *number) /* integer to string; return a pointer to null-terminated static const string */ -static char integer_buffer[MAX_INTEGER_DIGITS] = {'\0'}; -#define end_of_integer_buffer (integer_buffer + MAX_INTEGER_DIGITS - 1) - -/* writing integers */ +#define end_of_integer_buffer(integer_buffer) (integer_buffer + MAX_INTEGER_DIGITS - 1) #define number_printrev_signed(p, number, quotient) \ do { \ @@ -292,63 +311,59 @@ static char integer_buffer[MAX_INTEGER_DIGITS] = {'\0'}; *--p = (char)(quotient - integer_multiplied10(number)) + '0'; \ } while (number) -char * int32_as_string (int32_t number, char **e) +#define SINTTYPE_AS_STRING(inttype, number, ibuf, psize) \ + char *p, *e; \ + inttype quotient; \ + e = p = end_of_integer_buffer(ibuf); *p = '\0'; \ + number_printrev_signed(p, number, quotient); \ + *psize = (size_t)(e - p) + +#define UINTTYPE_AS_STRING(inttype, number, ibuf, psize) \ + char *p, *e; \ + inttype quotient; \ + e = p = end_of_integer_buffer(ibuf); *p = '\0'; \ + number_printrev_unsigned(p, number, quotient); \ + *psize = (size_t)(e - p) + +char * int32_as_string (int32_t number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - int quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_signed(p, number, quotient); + SINTTYPE_AS_STRING(int32_t, number, ibuf, psize); return p; } -char * intlw_as_string (intlw_t number, char **e) +char * slong_as_string (long number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - intlw_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_signed(p, number, quotient); + SINTTYPE_AS_STRING(long, number, ibuf, psize); return p; } -char * int64_as_string (int64_t number, char **e) +char * int64_as_string (int64_t number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - int64_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_signed(p, number, quotient); + SINTTYPE_AS_STRING(int64_t, number, ibuf, psize); return p; } -char * uint32_as_string (uint32_t number, char **e) +char * uint32_as_string (uint32_t number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - uint32_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_unsigned(p, number, quotient); + UINTTYPE_AS_STRING(uint32_t, number, ibuf, psize); return p; } -char * uintlw_as_string (uintlw_t number, char **e) +char * ulong_as_string (unsigned long number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - uintlw_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_unsigned(p, number, quotient); + UINTTYPE_AS_STRING(unsigned long, number, ibuf, psize); return p; } -char * uint64_as_string (uint64_t number, char **e) +char * usize_as_string (size_t number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - uint64_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_unsigned(p, number, quotient); + UINTTYPE_AS_STRING(size_t, number, ibuf, psize); + return p; +} + +char * uint64_as_string (uint64_t number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) +{ + UINTTYPE_AS_STRING(uint64_t, number, ibuf, psize); return p; } @@ -366,10 +381,10 @@ char * uint64_as_string (uint64_t number, char **e) *--p = base36_lc_palindrome[MAX_RADIX - 1 + (quotient - number*radix)]; \ } while (number) -#define number_printrev_signed_radix(p, number, radix, quotient) \ +#define number_printrev_signed_radix(p, number, radix, quotient, uc) \ do { \ - if (radix > 0) { number_printrev_signed_radix_uc(p, number, radix, quotient); } \ - else { radix = -radix; number_printrev_signed_radix_lc(p, number, radix, quotient); } \ + if (uc) { number_printrev_signed_radix_uc(p, number, radix, quotient); } \ + else { number_printrev_signed_radix_lc(p, number, radix, quotient); } \ if (quotient < 0) *--p = '-'; \ } while (0) @@ -385,69 +400,73 @@ char * uint64_as_string (uint64_t number, char **e) *--p = base36_lc_alphabet[quotient % radix]; \ } while (number) -#define number_printrev_unsigned_radix(p, number, radix, quotient) \ +#define number_printrev_unsigned_radix(p, number, radix, quotient, uc) \ do { \ - if (radix > 0) { number_printrev_unsigned_radix_uc(p, number, radix, quotient); } \ - else { radix = -radix; number_printrev_unsigned_radix_lc(p, number, radix, quotient); } \ + if (uc) { number_printrev_unsigned_radix_uc(p, number, radix, quotient); } \ + else { number_printrev_unsigned_radix_lc(p, number, radix, quotient); } \ } while (0) -char * int32_as_radix (int number, int radix, char **e) +#define SINTTYPE_AS_RADIX(inttype, number, radix, uc, ibuf, psize) \ + char *p, *e; \ + inttype quotient; \ + e = p = end_of_integer_buffer(ibuf); *p = '\0'; \ + number_printrev_signed_radix(p, number, radix, quotient, uc); \ + *psize = (size_t)(e - p) + +#define UINTTYPE_AS_RADIX(inttype, number, radix, uc, ibuf, psize) \ + char *p, *e; \ + inttype quotient; \ + e = p = end_of_integer_buffer(ibuf); *p = '\0'; \ + number_printrev_unsigned_radix(p, number, radix, quotient, uc); \ + *psize = (size_t)(e - p) + +char * int32_as_radix (int32_t number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - int quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_signed_radix(p, number, radix, quotient); + SINTTYPE_AS_RADIX(int32_t, number, radix, uc, ibuf, psize); return p; } -char * intlw_as_radix (intlw_t number, int radix, char **e) +char * slong_as_radix (long number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - intlw_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_signed_radix(p, number, radix, quotient); + SINTTYPE_AS_RADIX(long, number, radix, uc, ibuf, psize); return p; } -char * int64_as_radix (int64_t number, int radix, char **e) +/* +char * ssize_as_radix (ssize_t number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - int64_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_signed_radix(p, number, radix, quotient); + SINTTYPE_AS_RADIX(ssize_t, number, radix, uc, ibuf, psize); return p; } +*/ -char * uint32_as_radix (uint32_t number, int radix, char **e) +char * int64_as_radix (int64_t number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - uint32_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_unsigned_radix(p, number, radix, quotient); + SINTTYPE_AS_RADIX(int64_t, number, radix, uc, ibuf, psize); return p; } -char * uintlw_as_radix (uintlw_t number, int radix, char **e) +char * uint32_as_radix (uint32_t number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - uintlw_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_unsigned_radix(p, number, radix, quotient); + UINTTYPE_AS_RADIX(uint32_t, number, radix, uc, ibuf, psize); return p; } -char * uint64_as_radix (uint64_t number, int radix, char **e) +char * ulong_as_radix (unsigned long number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - uint64_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_unsigned_radix(p, number, radix, quotient); + UINTTYPE_AS_RADIX(unsigned long, number, radix, uc, ibuf, psize); + return p; +} + +char * usize_as_radix (size_t number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) +{ + UINTTYPE_AS_RADIX(size_t, number, radix, uc, ibuf, psize); + return p; +} + +char * uint64_as_radix (uint64_t number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) +{ + UINTTYPE_AS_RADIX(uint64_t, number, radix, uc, ibuf, psize); return p; } @@ -463,7 +482,14 @@ const char * alpha_to_uint32 (const char *s, uint32_t *number) return s; } -const char * alpha_to_uintlw (const char *s, uintlw_t *number) +const char * alpha_to_ulong (const char *s, unsigned long *number) +{ + int c; + string_scan_alpha(s, c, *number, 26); + return s; +} + +const char * alpha_to_usize (const char *s, size_t *number) { int c; string_scan_alpha(s, c, *number, 26); @@ -489,232 +515,132 @@ const char * alpha_to_uint64 (const char *s, uint64_t *number) *--p = base26_lc_alphabet[quotient % radix]; \ } -char * uint32_as_alpha_uc (uint32_t number, char **e) -{ - char *p; - uint32_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_unsigned_alpha_uc(p, number, 26, quotient); - return p; -} +#define UINTTYPE_AS_ALPHA(inttype, number, uc, ibuf, psize) \ + char *p, *e; \ + inttype quotient; \ + e = p = end_of_integer_buffer(ibuf); *p = '\0'; \ + if (uc) { number_printrev_unsigned_alpha_uc(p, number, 26, quotient); } \ + else { number_printrev_unsigned_alpha_lc(p, number, 26, quotient); } \ + *psize = (size_t)(e - p) -char * uint32_as_alpha_lc (uint32_t number, char **e) +char * uint32_as_alpha (uint32_t number, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - uint32_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_unsigned_alpha_lc(p, number, 26, quotient); + UINTTYPE_AS_ALPHA(uint32_t, number, uc, ibuf, psize); return p; } -char * uintlw_as_alpha_uc (uintlw_t number, char **e) +char * ulong_as_alpha (unsigned long number, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - uintlw_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_unsigned_alpha_uc(p, number, 26, quotient); + UINTTYPE_AS_ALPHA(unsigned long, number, uc, ibuf, psize); return p; } -char * uintlw_as_alpha_lc (uintlw_t number, char **e) +char * usize_as_alpha (size_t number, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - uintlw_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_unsigned_alpha_lc(p, number, 26, quotient); + UINTTYPE_AS_ALPHA(size_t, number, uc, ibuf, psize); return p; } -char * uint64_as_alpha_uc (uint64_t number, char **e) +char * uint64_as_alpha (uint64_t number, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize) { - char *p; - uint64_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_unsigned_alpha_uc(p, number, 26, quotient); - return p; -} - -char * uint64_as_alpha_lc (uint64_t number, char **e) -{ - char *p; - uint64_t quotient; - p = end_of_integer_buffer; *p = '\0'; - if (e != NULL) *e = p; - number_printrev_unsigned_alpha_lc(p, number, 26, quotient); + UINTTYPE_AS_ALPHA(uint64_t, number, uc, ibuf, psize); return p; } -/* a variant of alphabetic, a, b, c, ..., z, aa, bb, cc, ..., zz (eg. pdf page labelling) */ +/* a variant of alphabetic, a, b, c, ..., z, aa, bb, cc, ..., zz (eg. pdf page labelling) + watch out: unsafe for large numbers; for buffer size N we can handle max. N * 26. */ #define string_scan_alphan(s, c, number, radix) \ do { \ number = 0; \ - if ((c = base26_value(*s)) > 0) { \ + if ((c = (uint16_t)base26_value(*s)) > 0) { \ number = c; \ - while (c == base26_value(*++s)) number += radix; \ + while (c == (uint16_t)base26_value(*++s)) number += radix; \ } \ } while (0) -const char * alphan_to_uint32 (const char *s, uint32_t *number) -{ - int c; - string_scan_alphan(s, c, *number, 26); - return s; -} - -const char * alphan_to_uintlw (const char *s, uintlw_t *number) +const char * alphan_to_uint16 (const char *s, uint16_t *number) { - int c; + uint16_t c; string_scan_alphan(s, c, *number, 26); return s; } -const char * alphan_to_uint64 (const char *s, uintlw_t *number) -{ - int c; - string_scan_alphan(s, c, *number, 26); - return s; -} - -#define number_print_alphan_uc(s, c, number, radix) \ - if (number > 0) { \ - for (c = (--number) % radix, number -= c; ; number -= radix) { \ - *s++ = base26_uc_alphabet[c]; \ - if (number == 0 || p >= end_of_integer_buffer) break; \ - } \ +#define number_print_alphan_uc(p, e, c, number, radix) \ + for (c = (--number) % radix, number -= c; ; number -= radix) { \ + *p++ = base26_uc_alphabet[c]; \ + if (number == 0 || p >= e) break; \ } -#define number_print_alphan_lc(s, c, number, radix) \ - if (number > 0) { \ - for (c = (--number) % radix, number -= c; ; number -= radix) { \ - *s++ = base26_lc_alphabet[c]; \ - if (number == 0 || p >= end_of_integer_buffer) break; \ - } \ +#define number_print_alphan_lc(p, e, c, number, radix) \ + for (c = (--number) % radix, number -= c; ; number -= radix) { \ + *p++ = base26_lc_alphabet[c]; \ + if (number == 0 || p >= e) break; \ } -char * uint32_as_alphan_uc (uint32_t number, char **e) -{ - char *p; - uint8_t c; - p = integer_buffer; - number_print_alphan_uc(p, c, number, 26); - *p = '\0'; if (e != NULL) *e = p; - return integer_buffer; -} - -char * uint32_as_alphan_lc (uint32_t number, char **e) -{ - char *p; - uint8_t c; - p = integer_buffer; - number_print_alphan_lc(p, c, number, 26); - *p = '\0'; if (e != NULL) *e = p; - return integer_buffer; -} - -char * uintlw_as_alphan_uc (uintlw_t number, char **e) -{ - char *p; - uint8_t c; - p = integer_buffer; - number_print_alphan_uc(p, c, number, 26); - *p = '\0'; if (e != NULL) *e = p; - return integer_buffer; -} - -char * uintlw_as_alphan_lc (uintlw_t number, char **e) -{ - char *p; - uint8_t c; - p = integer_buffer; - number_print_alphan_lc(p, c, number, 26); - *p = '\0'; if (e != NULL) *e = p; - return integer_buffer; -} - -char * uint64_as_alphan_uc (uint64_t number, char **e) -{ - char *p; - uint8_t c; - p = integer_buffer; - number_print_alphan_uc(p, c, number, 26); - *p = '\0'; if (e != NULL) *e = p; - return integer_buffer; -} +#define UINTTYPE_AS_ALPHAN(inttype, number, uc, ibuf, size, psize) \ + char *p, *e; \ + uint8_t c; \ + p = ibuf; \ + e = p + size; \ + if (number > 0) { \ + if (uc) { number_print_alphan_uc(p, e, c, number, 26); } \ + else { number_print_alphan_lc(p, e, c, number, 26); } \ + } \ + *p = '\0'; \ + *psize = (size_t)(p - ibuf) -char * uint64_as_alphan_lc (uint64_t number, char **e) +char * uint16_as_alphan (uint16_t number, int uc, char ibuf[], size_t size, size_t *psize) { - char *p; - uint8_t c; - p = integer_buffer; - number_print_alphan_lc(p, c, number, 26); - *p = '\0'; if (e != NULL) *e = p; - return integer_buffer; + UINTTYPE_AS_ALPHAN(uint16_t, number, uc, ibuf, size, psize); + return ibuf; } /* roman numeral */ -/* todo: large roman numerals? http://mathforum.org/library/drmath/view/57569.html */ +/* large roman numerals? http://mathforum.org/library/drmath/view/57569.html */ #define base_roman_uc_alphabet "MDCLXVI" #define base_roman_lc_alphabet "mdclxvi" -static const uint32_t base_roman_values[] = { 1000, 500, 100, 50, 10, 5, 1 }; - -#define integer_to_roman(p, number, alphabet) \ - { \ - uint32_t k, j, v, u; \ - for (j = 0, v = base_roman_values[0]; number > 0; ) \ - { \ - if (number >= v) \ - { \ - *p++ = alphabet[j]; \ - number -= v; \ - continue; \ - } \ - if (j & 1) \ - k = j + 1; \ - else \ - k = j + 2; \ - u = base_roman_values[k]; \ - if (number + u >= v) \ - { \ - *p++ = alphabet[k]; \ - number += u; \ - } \ - else \ - v = base_roman_values[++j]; \ - } \ - } - -char * uint16_as_roman_uc (uint16_t number, char **e) +char * uint16_as_roman (uint16_t number, int uc, char ibuf[MAX_ROMAN_DIGITS], size_t *psize) { - char *p = integer_buffer; - integer_to_roman(p, number, base_roman_uc_alphabet); - if (e != NULL) - *e = p; - *p = '\0'; - return integer_buffer; -} + static const uint32_t base_roman_values[] = { 1000, 500, 100, 50, 10, 5, 1 }; + const char *alphabet; + char *p; + uint32_t k, j, v, u, n; -char * uint16_as_roman_lc (uint16_t number, char **e) -{ - char *p = integer_buffer; - integer_to_roman(p, number, base_roman_lc_alphabet); - if (e != NULL) - *e = p; + n = (uint32_t)number; // uint16_t used to limit leding 'M' + alphabet = uc ? base_roman_uc_alphabet : base_roman_lc_alphabet; + for (p = ibuf, j = 0, v = base_roman_values[0]; n > 0; ) + { + if (n >= v) + { + *p++ = alphabet[j]; + n -= v; + continue; + } + if (j & 1) + k = j + 1; + else + k = j + 2; + u = base_roman_values[k]; + if (n + u >= v) + { + *p++ = alphabet[k]; + n += u; + } + else + v = base_roman_values[++j]; + } *p = '\0'; - return integer_buffer; + *psize = (size_t)(p - ibuf); + return ibuf; } /* IEEE-754 */ -#define BINARY_MODF 1 +#define BINARY_MODF 1 #define NOT_A_NUMBER_STRING "NaN" #define INFINITY_STRING "INF" @@ -753,7 +679,6 @@ typedef struct ieee_float { #define ieee_double_fraction(i) (i & 0x000fffffffffffffull) #define ieee_double_exponent(i) ((0x7ff & (i >> 52)) - IEEE_DOUBLE_BIAS) -#define ieee_double_sign(ieee_number) ((void)((ieee_number.sign = ieee_number.bits >> 63) && (ieee_number.number = -ieee_number.number))) #define ieee_double_init(ieee_number, number) \ ieee_number.number = number, \ ieee_number.fraction = ieee_double_fraction(ieee_number.bits), \ @@ -761,7 +686,6 @@ typedef struct ieee_float { #define ieee_float_fraction(i) (i & 0x007fffff) #define ieee_float_exponent(i) ((0xff & (i >> 23)) - IEEE_FLOAT_BIAS) -#define ieee_float_sign(ieee_number) ((void)((ieee_number.sign = ieee_number.bits >> 31) && (ieee_number.number = -ieee_number.number))) #define ieee_float_init(ieee_number, number) \ ieee_number.number = number, \ ieee_number.fraction = ieee_float_fraction(ieee_number.bits), \ @@ -956,10 +880,6 @@ const float float_decimal_negpower10[] = { ieee_number_decimal(ieee_double_binary_fraction, ieee_number, exponent10, digits, p) #define ieee_float_decimal(ieee_number, exponent10, digits, p) \ ieee_number_decimal(ieee_float_binary_fraction, ieee_number, exponent10, digits, p) -#define ieee_double_decimal_dot(ieee_number, exponent10, digits, p, dot) \ - ieee_number_decimal_dot(ieee_double_binary_fraction, ieee_number, exponent10, digits, p, dot) -#define ieee_float_decimal_dot(ieee_number, exponent10, digits, p, dot) \ - ieee_number_decimal_dot(ieee_float_binary_fraction, ieee_number, exponent10, digits, p, dot) #else @@ -972,10 +892,6 @@ const float float_decimal_negpower10[] = { ieee_number_decimal(ieee_double_decimal_fraction, ieee_number, exponent10, digits, p) #define ieee_float_decimal(ieee_number, exponent10, digits, p) \ ieee_number_decimal(ieee_float_decimal_fraction, ieee_number, exponent10, digits, p) -#define ieee_double_decimal_dot(ieee_number, exponent10, digits, p, dot) \ - ieee_number_decimal_dot(ieee_double_decimal_fraction, ieee_number, exponent10, digits, p, dot) -#define ieee_float_decimal_dot(ieee_number, exponent10, digits, p, dot) \ - ieee_number_decimal_dot(ieee_float_decimal_fraction, ieee_number, exponent10, digits, p, dot) #endif @@ -992,24 +908,6 @@ const float float_decimal_negpower10[] = { for ( ; digits && ieee_number.fraction; --digits) \ *p++ = '0' + (char)method(ieee_number) -#define ieee_number_decimal_dot(method, ieee_number, exponent10, digits, p, dot) \ - ieee_double_denormalize(ieee_number); \ - if (ieee_number.sign) *p++ = '-'; \ - if (exponent10 <= 0) \ - { \ - *p++ = '0'; \ - if (dot != NULL) *dot = p; \ - for (*p++ = RADIX_CHAR; exponent10 && digits; *p++ = '0', ++exponent10, --digits); \ - } \ - else \ - { \ - do { *p++ = '0' + (char)method(ieee_number); } while (--exponent10); \ - if (dot != NULL) *dot = p; \ - *p++ = RADIX_CHAR; \ - } \ - for ( ; digits && ieee_number.fraction; --digits) \ - *p++ = '0' + (char)method(ieee_number) - /* rounding to nearest integer */ #if BINARY_MODF @@ -1064,123 +962,77 @@ const float float_decimal_negpower10[] = { /* double to decimal */ -static char number_buffer[512]; - -#define ieee_copy_special_string(special, p, _p) \ - for (p = (char *)number_buffer, _p = special; ; ++p, ++_p) { \ +#define ieee_copy_special_string(nbuf, special, p, _p) \ + for (p = nbuf, _p = special; ; ++p, ++_p) { \ if ((*p = *_p) == '\0') break; \ } -#define ieee_copy_special_string_re(special, p, _p, r, e) \ - for (p = (char *)number_buffer, _p = special; ; ++p, ++_p) { \ +#define ieee_copy_special_string_re(nbuf, special, p, _p, r, e) \ + for (p = nbuf, _p = special; ; ++p, ++_p) { \ if ((*p = *_p) == '\0') { \ - if (r != NULL) *r = NULL; \ - if (e != NULL) *e = p; \ + if (r != NULL) *r = NULL; \ + if (e != NULL) *e = p; \ break; \ } \ } -char * double_to_string (double number, int digits) +char * double_as_string (double number, int digits, char nbuf[MAX_NUMBER_DIGITS], size_t *psize) { ieee_double ieee_number; int exponent10; char *s, *p; const char *_p; + s = p = nbuf + 1; // for sign/rounding ieee_double_init(ieee_number, number); - ieee_double_sign(ieee_number); + if ((ieee_number.sign = ieee_number.bits >> 63) != 0) + ieee_number.number = -ieee_number.number; if (ieee_double_is_zero(ieee_number)) // to avoid crash on log10(number) { - ieee_copy_special_string(ieee_double_zero_string(ieee_number), p, _p); - return (char *)number_buffer; + ieee_copy_special_string(nbuf, ieee_double_zero_string(ieee_number), p, _p); + *psize = (size_t)(p - nbuf); + return nbuf; } if (ieee_double_special_case(ieee_number)) { - ieee_copy_special_string(ieee_double_special_string(ieee_number), p, _p); - return (char *)number_buffer; + ieee_copy_special_string(nbuf, ieee_double_special_string(ieee_number), p, _p); + *psize = (size_t)(p - nbuf); + return nbuf; } - s = p = number_buffer + 1; ieee_double_exp10(ieee_number, exponent10); ieee_double_decimal(ieee_number, exponent10, digits, p); ieee_double_round(ieee_number, exponent10, s, p); *p = '\0'; - return s; -} - -char * double_as_string (double number, int digits, char **r, char **e) -{ - ieee_double ieee_number; - int exponent10; - char *s, *p; const char *_p; - s = p = number_buffer + 1; - ieee_double_init(ieee_number, number); - ieee_double_sign(ieee_number); - if (ieee_double_is_zero(ieee_number)) // to avoid crash on log10(number) - { - ieee_copy_special_string_re(ieee_double_zero_string(ieee_number), p, _p, r, e); - return (char *)number_buffer; - } - if (ieee_double_special_case(ieee_number)) - { - ieee_copy_special_string_re(ieee_double_special_string(ieee_number), p, _p, r, e); - return (char *)number_buffer; - } - ieee_double_exp10(ieee_number, exponent10); - ieee_double_decimal_dot(ieee_number, exponent10, digits, p, r); - ieee_double_round(ieee_number, exponent10, s, p); - if (e != NULL) *e = p; - *p = '\0'; + *psize = (size_t)(p - s); return s; } /* float to decimal */ -char * float_to_string (float number, int digits) +char * float_as_string (float number, int digits, char nbuf[MAX_NUMBER_DIGITS], size_t *psize) { ieee_float ieee_number; int exponent10; char *s, *p; const char *_p; + s = p = nbuf + 1; // for sign/rounding ieee_float_init(ieee_number, number); - ieee_float_sign(ieee_number); + if ((ieee_number.sign = ieee_number.bits >> 31) != 0) + ieee_number.number = -ieee_number.number; if (ieee_float_is_zero(ieee_number)) { - ieee_copy_special_string(ieee_float_zero_string(ieee_number), p, _p); - return (char *)number_buffer; + ieee_copy_special_string(nbuf, ieee_float_zero_string(ieee_number), p, _p); + *psize = (size_t)(p - nbuf); + return nbuf; } if (ieee_float_special_case(ieee_number)) { - ieee_copy_special_string(ieee_float_special_string(ieee_number), p, _p); - return (char *)number_buffer; + ieee_copy_special_string(nbuf, ieee_float_special_string(ieee_number), p, _p); + *psize = (size_t)(p - nbuf); + return nbuf; } - s = p = number_buffer + 1; ieee_float_exp10(ieee_number, exponent10); ieee_float_decimal(ieee_number, exponent10, digits, p); ieee_float_round(ieee_number, exponent10, s, p); *p = '\0'; - return s; -} - -char * float_as_string (float number, int digits, char **r, char **e) -{ - ieee_float ieee_number; - int exponent10; - char *s, *p; const char *_p; - s = p = number_buffer + 1; - ieee_float_init(ieee_number, number); - ieee_float_sign(ieee_number); - if (ieee_float_is_zero(ieee_number)) - { - ieee_copy_special_string_re(ieee_float_zero_string(ieee_number), p, _p, r, e); - return (char *)number_buffer; - } - if (ieee_float_special_case(ieee_number)) - { - ieee_copy_special_string_re(ieee_float_special_string(ieee_number), p, _p, r, e); - return (char *)number_buffer; - } - ieee_float_exp10(ieee_number, exponent10); - ieee_float_decimal_dot(ieee_number, exponent10, digits, p, r); - ieee_float_round(ieee_number, exponent10, s, p); - if (e != NULL) *e = p; - *p = '\0'; + *psize = (size_t)(p - s); return s; } @@ -1289,7 +1141,7 @@ size_t bytes_to_hex_uc (const void *input, size_t size, unsigned char *output) { size_t i; const unsigned char *p; - for (i = 0, p = (const unsigned char *)input; i < size; ++i, ++p) + for (i = 0, p = (const unsigned char *)input; i < size; ++i, ++p) { *output++ = base16_uc_digit1(*p); *output++ = base16_uc_digit2(*p); @@ -1322,4 +1174,4 @@ void print_as_hex (const void *input, size_t bytes) const unsigned char *p; for (p = (const unsigned char *)input; bytes > 0; --bytes, ++p) printf("%02x", *p); -}
\ No newline at end of file +} diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilnumber.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilnumber.h new file mode 100644 index 00000000000..735432b8dd8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilnumber.h @@ -0,0 +1,428 @@ +#ifndef UTIL_NUMBER_H +#define UTIL_NUMBER_H + +#include <stddef.h> // for size_t + +#include "utilplat.h" +#include "utildecl.h" + +#if defined(__cplusplus) && defined(_MSC_VER) +// int*_t types are in standard in msvc++ +#else +# include <stdint.h> +#endif + +/* 'long' isn't long for msvc64/mingw64, we need a type for machine word */ + +#if defined(_WIN64) || defined(__MINGW32__) +# define INT64F "%I64d" +# define UINT64F "%I64u" +#else +# define INT64F "%lld" +# define UINT64F "%llu" +#endif + +#if defined(MSVC64) +# define INTLW_IS_INT64 +# define intlw_t int64_t +# define uintlw_t uint64_t +# define INTLW(N) N##I64 +# define UINTLW(N) N##UI64 +# define INTLWF INT64F +# define UINTLWF UINT64F +#elif defined(__MINGW64__) +# define INTLW_IS_INT64 +# define intlw_t int64_t +# define uintlw_t uint64_t +# define INTLW(N) N##LL +# define UINTLW(N) N##ULL +# define INTLWF INT64F +# define UINTLWF UINT64F +#else // 32bit or sane 64bit (LP64) +# define INTLW_IS_LONG +# define intlw_t long +# define uintlw_t unsigned long +# define INTLW(N) N##L +# define UINTLW(N) N##UL +# define INTLWF "%ld" +# define UINTLWF "%lu" +#endif + +// ssize_t is missing in MSVC, but defining it is risky; some environments (eg. python) typedefs ssize_t on its own way.. +// #if defined(MSVC64) +// # define ssize_t int32_t +// #else +// # if defined(MSVC32) +// # define ssize_t int64_t +// # endif +// #endif + +/* basic constants */ + +#define MAX_RADIX 36 +#define MAX_INTEGER_DIGITS 65 /* 64-bit number in binary form plus '\0' */ +#define MAX_ROMAN_DIGITS 128 /* to handle romannumeral of short int (up to 65 leading 'M') */ +#define MAX_NUMBER_DIGITS 512 +#define NUMBER_BUFFER_SIZE MAX_NUMBER_DIGITS + +#define base36_uc_alphabet "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define base36_lc_alphabet "0123456789abcdefghijklmnopqrstuvwxyz" + +#define base26_uc_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define base26_lc_alphabet "abcdefghijklmnopqrstuvwxyz" +extern const int base26_lookup[]; + +#define base36_lc_palindrome "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" +#define base36_uc_palindrome "ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + +extern const int base36_lookup[]; + +#define base10_palindrome "9876543210123456789" +#define base10_alphabet "0123456789" +extern const int base10_lookup[]; + +#define base16_uc_alphabet "0123456789ABCDEF" +#define base16_lc_alphabet "0123456789abcdef" +extern const int base16_lookup[]; + +#define base16_uc_digit1(c) base16_uc_alphabet[(c)>>4] +#define base16_uc_digit2(c) base16_uc_alphabet[(c)&15] +#define base16_lc_digit1(c) base16_lc_alphabet[(c)>>4] +#define base16_lc_digit2(c) base16_lc_alphabet[(c)&15] + +#define base8_digit(c) ((unsigned)(c - '0') <= (unsigned)('7' - '0')) +#define base8_value(c) (base8_digit(c) ? (c) - '0' : -1) + +#define base10_digit(c) ((unsigned)(c - '0') <= (unsigned)('9' - '0')) +#define base10_value(c) (base10_lookup[(uint8_t)(c)]) + +#define base16_digit(c) (base16_lookup[(uint8_t)(c)] >= 0) +#define base16_value(c) (base16_lookup[(uint8_t)(c)]) + +#define base26_digit(c) (base26_lookup[(uint8_t)(c)] >= 0) +#define base26_value(c) (base26_lookup[(uint8_t)(c)]) + +#define base36_digit(c) (base36_lookup[(uint8_t)(c)] >= 0) +#define base36_value(c) (base36_lookup[(uint8_t)(c)]) + +//#define base_digit(c, radix) ((unsigned)(base36_lookup[c]) < (unsigned)(radix)) +//#define base_value(c, radix) (base_digit(c, radix) ? base36_lookup[c] : -1) + +UTILDEF extern char util_number_buffer[NUMBER_BUFFER_SIZE]; + +/* integer from string; return a pointer to character next to the last digit */ + +UTILAPI const char * string_to_int32 (const char *s, int32_t *number); +UTILAPI const char * string_to_slong (const char *s, long *number); +UTILAPI const char * string_to_int64 (const char *s, int64_t *number); + +UTILAPI const char * string_to_uint32 (const char *s, uint32_t *number); +UTILAPI const char * string_to_ulong (const char *s, unsigned long *number); +UTILAPI const char * string_to_usize (const char *s, size_t *number); +UTILAPI const char * string_to_uint64 (const char *s, uint64_t *number); + +UTILAPI const char * radix_to_int32 (const char *s, int32_t *number, int radix); +UTILAPI const char * radix_to_slong (const char *s, long *number, int radix); +UTILAPI const char * radix_to_int64 (const char *s, int64_t *number, int radix); + +UTILAPI const char * radix_to_uint32 (const char *s, uint32_t *number, int radix); +UTILAPI const char * radix_to_ulong (const char *s, unsigned long *number, int radix); +UTILAPI const char * radix_to_usize (const char *s, size_t *number, int radix); +UTILAPI const char * radix_to_uint64 (const char *s, uint64_t *number, int radix); + +UTILAPI const char * alpha_to_uint32 (const char *s, uint32_t *number); +UTILAPI const char * alpha_to_ulong (const char *s, unsigned long *number); +UTILAPI const char * alpha_to_usize (const char *s, size_t *number); +UTILAPI const char * alpha_to_uint64 (const char *s, uint64_t *number); + +/* integer to string */ + +UTILAPI char * int32_as_string (int32_t number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * slong_as_string (long number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * int64_as_string (int64_t number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); + +#define int32_to_string(number, psize) int32_as_string(number, util_number_buffer, psize) +#define slong_to_string(number, psize) slong_as_string(number, util_number_buffer, psize) +#define int64_to_string(number, psize) int64_as_string(number, util_number_buffer, psize) + +UTILAPI char * uint32_as_string (uint32_t number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * ulong_as_string (unsigned long number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * usize_as_string (size_t number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * uint64_as_string (uint64_t number, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); + +#define uint32_to_string(number, psize) uint32_as_string(number, util_number_buffer, psize) +#define ulong_to_string(number, psize) ulong_as_string(number, util_number_buffer, psize) +#define usize_to_string(number, psize) usize_as_string(number, util_number_buffer, psize) +#define uint64_to_string(number, psize) uint64_as_string(number, util_number_buffer, psize) + +UTILAPI char * int32_as_radix (int32_t number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * slong_as_radix (long number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * int64_as_radix (int64_t number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); + +#define int32_to_radix(number, radix, uc, psize) int32_as_radix(number, radix, uc, util_number_buffer, psize) +#define slong_to_radix(number, radix, uc, psize) slong_as_radix(number, radix, uc, util_number_buffer, psize) +#define int64_to_radix(number, radix, uc, psize) int64_as_radix(number, radix, uc, util_number_buffer, psize) + +UTILAPI char * uint32_as_radix (uint32_t number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * ulong_as_radix (unsigned long number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * usize_as_radix (size_t number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * uint64_as_radix (uint64_t number, int radix, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); + +#define uint32_to_radix(number, radix, uc, psize) uint32_as_radix(number, radix, uc, util_number_buffer, psize) +#define ulong_to_radix(number, radix, uc, psize) ulong_as_radix(number, radix, uc, util_number_buffer, psize) +#define usize_to_radix(number, radix, uc, psize) usize_as_radix(number, radix, uc, util_number_buffer, psize) +#define uint64_to_radix(number, radix, uc, psize) uint64_as_radix(number, radix, uc, util_number_buffer, psize) + +UTILAPI char * uint32_as_alpha (uint32_t number, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * ulong_as_alpha (unsigned long number, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * usize_as_alpha (size_t number, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); +UTILAPI char * uint64_as_alpha (uint64_t number, int uc, char ibuf[MAX_INTEGER_DIGITS], size_t *psize); + +#define uint32_to_alpha(number, uc, psize) uint32_as_alpha(number, uc, util_number_buffer, psize) +#define ulong_to_alpha(number, uc, psize) ulong_as_alpha(number, uc, util_number_buffer, psize) +#define usize_to_alpha(number, uc, psize) usize_as_alpha(number, uc, util_number_buffer, psize) +#define uint64_to_alpha(number, uc, psize) uint64_as_alpha(number, uc, util_number_buffer, psize) + +#if defined(INTLW_IS_INT64) + +# define string_to_intlw(s, number) string_to_int64(s, number) +# define string_to_uintlw(s, number) string_to_uint64(s, number) + +# define radix_to_intlw(s, number, radix) radix_to_int64(s, number, radix) +# define radix_to_uintlw(s, number, radix) radix_to_uint64(s, number, radix) + +# define alpha_to_uintlw(s, number) alpha_to_uint64(s, number) + +# define intlw_as_string(number, ibuf, psize) int64_as_string(number, ibuf, psize) +# define uintlw_as_string(number, ibuf, psize) uint64_as_string(number, ibuf, psize) + +# define intlw_to_string(number, psize) int64_to_string(number, psize) +# define uintlw_to_string(number, psize) uint64_to_string(number, psize) + +# define intlw_as_radix(number, radix, uc, ibuf, psize) int64_as_radix(number, radix, uc, ibuf, psize) +# define uintlw_as_radix(number, radix, uc, ibuf, psize) uint64_as_radix(number, radix, uc, ibuf, psize) + +# define intlw_to_radix(number, radix, uc, psize) int64_to_radix(number, radix, uc, psize) +# define uintlw_to_radix(number, radix, uc, psize) uint64_to_radix(number, radix, uc, psize) + +# define uintlw_as_alpha(number, uc, ibuf, psize) uint64_as_alpha(number, uc, ibuf, psize) +# define uintlw_to_alpha(number, uc, psize) uint64_to_alpha(number, uc, ibuf, psize) + +#elif defined(INTLW_IS_LONG) + +# define string_to_intlw(s, number) string_to_slong(s, number) +# define string_to_uintlw(s, number) string_to_ulong(s, number) + +# define radix_to_intlw(s, number, radix) radix_to_slong(s, number, radix) +# define radix_to_uintlw(s, number, radix) radix_to_ulong(s, number, radix) + +# define alpha_to_uintlw(s, number) alpha_to_ulong(s, number) + +# define intlw_as_string(number, ibuf, psize) slong_as_string(number, ibuf, psize) +# define uintlw_as_string(number, ibuf, psize) ulong_as_string(number, ibuf, psize) + +# define intlw_to_string(number, psize) slong_to_string(number, psize) +# define uintlw_to_string(number, psize) ulong_to_string(number, psize) + +# define intlw_as_radix(number, radix, uc, ibuf, psize) slong_as_radix(number, radix, uc, ibuf, psize) +# define uintlw_as_radix(number, radix, uc, ibuf, psize) ulong_as_radix(number, radix, uc, ibuf, psize) + +# define intlw_to_radix(number, radix, uc, psize) slong_to_radix(number, radix, uc, psize) +# define uintlw_to_radix(number, radix, uc, psize) ulong_to_radix(number, radix, uc, psize) + +# define uintlw_as_alpha(number, uc, ibuf, psize) ulong_as_alpha(number, uc, ibuf, psize) +# define uintlw_to_alpha(number, uc, psize) ulong_to_alpha(number, uc, ibuf, psize) + +#endif + +/* a..z, aa..zz, aaa..zzz (limited to uint16_t, valid for N <= buffer_size * 26) */ + +UTILAPI const char * alphan_to_uint16 (const char *s, uint16_t *number); +UTILAPI char * uint16_as_alphan (uint16_t number, int uc, char ibuf[], size_t size, size_t *psize); +#define uint16_to_alphan(number, uc, psize) uint16_as_alphan(number, uc, util_number_buffer, NUMBER_BUFFER_SIZE, psize) + +/* roman numeral (limited to uint16_t) */ + +UTILAPI const char * roman_to_uint16 (const char *s, uint16_t *number); +UTILAPI char * uint16_as_roman (uint16_t number, int uc, char ibuf[MAX_ROMAN_DIGITS], size_t *psize); +#define uint16_to_roman(number, uc, psize) uint16_as_roman(number, uc, util_number_buffer, psize) + +/* double/float to string */ + +UTILAPI char * double_as_string (double number, int digits, char nbuf[MAX_NUMBER_DIGITS], size_t *psize); +#define double_to_string(number, digits, psize) double_as_string(number, digits, util_number_buffer, psize) + +UTILAPI char * float_as_string (float number, int digits, char nbuf[MAX_NUMBER_DIGITS], size_t *psize); +#define float_to_string(number, digits, psize) float_as_string(number, digits, util_number_buffer, psize) + +/* string to double/float */ + +UTILAPI const char * string_to_double (const char *s, double *number); +UTILAPI const char * string_to_float (const char *s, float *number); + +/* convenience form accepting comma among a dot, with not exp notation (eg. pdf) */ + +UTILAPI const char * convert_to_double (const char *s, double *number); +UTILAPI const char * convert_to_float (const char *s, float *number); + +/* binary data parsers helpers */ + +#if 0 // masking gives more overactive warnings +#define get_number_byte1(n) ((n) & 0x000000ffu) +#define get_number_byte2(n) (((n) & 0x0000ff00u) >> 8) +#define get_number_byte3(n) (((n) & 0x00ff0000u) >> 16) +#define get_number_byte4(n) (((n) & 0xff000000u) >> 24) +#define get_number_byte5(n) (((n) & 0x000000ff00000000ull) >> 32) +#define get_number_byte6(n) (((n) & 0x0000ff0000000000ull) >> 40) +#define get_number_byte7(n) (((n) & 0x00ff000000000000ull) >> 48) +#define get_number_byte8(n) (((n) & 0xff00000000000000ull) >> 56) +#else +#define get_number_byte1(n) ((n) & 0xff) +#define get_number_byte2(n) (((n) >> 8) & 0xff) +#define get_number_byte3(n) (((n) >> 16) & 0xff) +#define get_number_byte4(n) (((n) >> 24) & 0xff) +#define get_number_byte5(n) (((n) >> 32) & 0xff) +#define get_number_byte6(n) (((n) >> 40) & 0xff) +#define get_number_byte7(n) (((n) >> 48) & 0xff) +#define get_number_byte8(n) (((n) >> 56) & 0xff) +#endif + +#define get_number_bytes_be1(n, b) (b[0] = (uint8_t)get_number_byte1(n)) +#define get_number_bytes_be2(n, b) (b[0] = (uint8_t)get_number_byte2(n), b[1] = (uint8_t)get_number_byte1(n)) +#define get_number_bytes_be3(n, b) (b[0] = (uint8_t)get_number_byte3(n), b[1] = (uint8_t)get_number_byte2(n), b[2] = (uint8_t)get_number_byte1(n)) +#define get_number_bytes_be4(n, b) (b[0] = (uint8_t)get_number_byte4(n), b[1] = (uint8_t)get_number_byte3(n), b[2] = (uint8_t)get_number_byte2(n), b[3] = (uint8_t)get_number_byte1(n)) + +#define get_number_bytes_be5(n, b) (b[0] = (uint8_t)get_number_byte5(n), b[1] = (uint8_t)get_number_byte4(n), b[2] = (uint8_t)get_number_byte3(n), b[3] = (uint8_t)get_number_byte2(n), \ + b[4] = (uint8_t)get_number_byte1(n)) +#define get_number_bytes_be6(n, b) (b[0] = (uint8_t)get_number_byte6(n), b[1] = (uint8_t)get_number_byte5(n), b[2] = (uint8_t)get_number_byte4(n), b[3] = (uint8_t)get_number_byte3(n), \ + b[4] = (uint8_t)get_number_byte2(n), b[5] = (uint8_t)get_number_byte1(n)) +#define get_number_bytes_be7(n, b) (b[0] = (uint8_t)get_number_byte7(n), b[1] = (uint8_t)get_number_byte6(n), b[2] = (uint8_t)get_number_byte5(n), b[3] = (uint8_t)get_number_byte4(n), \ + b[4] = (uint8_t)get_number_byte3(n), b[5] = (uint8_t)get_number_byte2(n), b[6] = (uint8_t)get_number_byte1(n)) +#define get_number_bytes_be8(n, b) (b[0] = (uint8_t)get_number_byte8(n), b[1] = (uint8_t)get_number_byte7(n), b[2] = (uint8_t)get_number_byte6(n), b[3] = (uint8_t)get_number_byte5(n), \ + b[4] = (uint8_t)get_number_byte4(n), b[5] = (uint8_t)get_number_byte3(n), b[6] = (uint8_t)get_number_byte2(n), b[7] = (uint8_t)get_number_byte1(n)) + +#define read_uint16be_as(s, int_type) ((int_type)((s[0]<<8)|s[1])) +#define read_uint32be_as(s, int_type) ((int_type)((s[0]<<24)|(s[1]<<16)|(s[2]<<8)|s[3])) + +#define read_uint16le_as(s, int_type) ((int_type)((s[1]<<8)|s[0])) +#define read_uint32le_as(s, int_type) ((int_type)((s[3]<<24)|(s[2]<<16)|(s[1]<<8)|s[0])) + +#define read_uint16_native(s) (*((uint16_t *)(s))) +#define read_uint32_native(s) (*((uint32_t *)(s))) +#define read_int16_native(s) (*((int16_t *)(s))) +#define read_int32_native(s) (*((int32_t *)(s))) + +#define scan_uint16be_as(s, int_type) (s += 2, (int_type)((s[-2]<<8)|s[-1])) +#define scan_uint32be_as(s, int_type) (s += 4, (int_type)((s[-4]<<24)|(s[-3]<<16)|(s[-2]<<8)|s[-1])) + +#define scan_uint16le_as(s, int_type) (s += 2, (int_type)((s[-1]<<8)|s[-2])) +#define scan_uint32le_as(s, int_type) (s += 4, (int_type)((s[-1]<<24)|(s[-2]<<16)|(s[-3]<<8)|s[-4])) + +#define scan_uint16_native(s) (s += 2, read_uint16_native(s-2)) +#define scan_uint32_native(s) (s += 4, read_uint32_native(s-4)) +#define scan_int16_native(s) (s += 2, read_int16_native(s-2)) +#define scan_int32_native(s) (s += 4, read_int32_native(s-4)) + +#define read_fixed16_16_as(s, float_type) (((float_type)read_uint32be_as(s, signed int))/(1<<16)) +#define read_fixed2_14_as(s, float_type) (((float_type)read_uint16be_as(s, signed short))/(1<<14)) + +#define scan_fixed16_16_as(s, float_type) (((float_type)scan_uint32be_as(s, signed int))/(1<<16)) +#define scan_fixed2_14_as(s, float_type) (((float_type)scan_uint16be_as(s, signed short))/(1<<14)) + +/* internal procedures */ + +#define _scan_sign(c, sign, next) \ + do { if (c == '-') { sign = 1; c = next; } else if (c == '+') { sign = 0; c = next; } else sign = 0; } while (0) + +#define integer_multiplied10(number) (((number) << 1) + ((number) << 3)) + +#define _scan_integer(c, number, next) \ + for (number = 0; base10_digit(c); number = integer_multiplied10(number) + (c - '0'), c = next) +#define _scan_radix(c, number, radix, next) \ + for (number = 0; (c = base36_value(c)) >= 0 && c < radix; number = number * radix + c, c = next) + +#define _read_integer(c, number, next) \ + for (number = c - '0', c = next; base10_digit(c); number = integer_multiplied10(number) + (c - '0'), c = next) +#define _read_radix(c, number, radix, next) \ + for (number = c - '0', c = next; (c = base36_value(c)) >= 0 && c < radix; number = number * radix + c, c = next) + +/* rationals */ + +#define _scan_decimal(c, number, next) \ + for (number = 0; base10_digit(c); number = number*10 + (c - '0'), c = next) +#define _scan_fraction(c, number, exponent10, next) \ + for (exponent10 = 0; base10_digit(c); --exponent10, number = number*10 + (c - '0'), c = next) + +#define _scan_exponent10(c, exponent10, next) \ + do { \ + int eexponent10, eexpsign; \ + _scan_sign(c, eexpsign, next); \ + _scan_integer(c, eexponent10, next); \ + if (eexpsign) \ + exponent10 -= eexponent10; \ + else \ + exponent10 += eexponent10; \ + } while(0) + +#if 0 + +// kept just for sentiment ;) + +extern const double double_binary_power10[]; +extern const float float_binary_power10[]; +extern const double double_binary_negpower10[]; +extern const float float_binary_negpower10[]; + +#define double_negative_exp10(number, exponent) \ +{ const double *bp10; int e = ((exponent) < 511 ? 511 : -(exponent)); \ + for (bp10 = double_binary_negpower10; e > 0; e >>= 1, ++bp10) \ + if (e & 1) number *= *bp10; } + +#define float_negative_exp10(number, exponent) \ +{ const float *bp10; int e = ((exponent) < 64 ? 64 : -(exponent)); \ + for (bp10 = float_binary_negpower10; e > 0; e >>= 1, ++bp10) \ + if (e & 1) number *= *bp10; } + +#define double_positive_exp10(number, exponent) \ +{ const double *bp10; int e = ((exponent) > 511 ? 511 : (exponent)); \ + for (bp10 = double_binary_power10; e > 0; e >>= 1, ++bp10) \ + if (e & 1) number *= *bp10; } + +#define float_positive_exp10(number, exponent) \ +{ const float *bp10; int e = ((exponent) > 64 ? 64 : (exponent)); \ + for (bp10 = double_binary_power10; e > 0; e >>= 1, ++bp10) \ + if (e & 1) number *= *bp10; } + +#define double_exp10(number, exponent) \ + if ((exponent) < 0) double_negative_exp10(number, exponent) else if ((exponent) > 0) double_positive_exp10(number, exponent) + +#define float_exp10(number, exponent) \ + if ((exponent) < 0) float_negative_exp10(number, exponent) else if ((exponent) > 0) float_positive_exp10(number, exponent) + +#else + +extern const double double_decimal_power10[]; +extern const float float_decimal_power10[]; +extern const double double_decimal_negpower10[]; +extern const float float_decimal_negpower10[]; + +#define double_negative_exp10(number, exponent) ((number) *= double_decimal_negpower10[(exponent) < -308 ? 308 : -(exponent)]) +#define double_positive_exp10(number, exponent) ((number) *= double_decimal_power10[(exponent) > 308 ? 308 : (exponent)]) + +#define float_negative_exp10(number, exponent) ((number) *= float_decimal_negpower10[(exponent) < -38 ? 38 : -(exponent)]) +#define float_positive_exp10(number, exponent) ((number) *= float_decimal_power10[(exponent) > 38 ? 38 : (exponent)]) + +#define double_exp10(number, exponent) ((void)(((exponent) < 0 && double_negative_exp10(number, exponent)) || (((exponent) > 0 && double_positive_exp10(number, exponent))))) +#define float_exp10(number, exponent) ((void)(((exponent) < 0 && float_negative_exp10(number, exponent)) || (((exponent) > 0 && float_positive_exp10(number, exponent))))) + +#endif + +/* pretty common stuff */ + +#define bytes_to_hex(input, size, output) bytes_to_hex_lc(input, size, output) +UTILAPI size_t bytes_to_hex_lc (const void *input, size_t size, uint8_t *output); +UTILAPI size_t bytes_to_hex_uc (const void *input, size_t size, uint8_t *output); +UTILAPI size_t hex_to_bytes (const void *input, size_t size, uint8_t *output); +UTILAPI void print_as_hex (const void *input, size_t bytes); + +#endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilplat.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilplat.h index 037a1e23199..8838f702b92 100644 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilplat.h +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilplat.h @@ -20,4 +20,12 @@ # endif #endif +#ifdef __GNUC__ +//# define FALLTHRU [[fallthrough]] // c++17 +//# define FALLTHRU [[gnu:fallthrough]] // c++14 +# define FALLTHRU __attribute__((fallthrough)); // C and C++03 +#else +# define FALLTHRU +#endif + #endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilsha.c b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilsha.c new file mode 100644 index 00000000000..596bf76f72b --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilsha.c @@ -0,0 +1,1065 @@ +/* sha2 implementation excerpted from code by Aaron D. Gifford */ + +/* + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ + */ + +#include <stdio.h> /* FILE */ +#include <string.h> /* memcpy()/memset() or bcopy()/bzero() */ +//#include <assert.h> /* assert() */ +#include "utilsha.h" + +/* + * UNROLLED TRANSFORM LOOP NOTE: + * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform + * loop version for the hash transform rounds (defined using macros + * later in this file). Either define on the command line, for example: + * + * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c + * + * or define below: + * + * #define SHA2_UNROLL_TRANSFORM + * + */ + +/*** SHA-256/384/512 Machine Architecture Definitions *****************/ +/* + * BYTE_ORDER NOTE: + * + * Please make sure that your system defines BYTE_ORDER. If your + * architecture is little-endian, make sure it also defines + * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are + * equivilent. + * + * If your system does not define the above, then you can do so by + * hand like this: + * + * #define LITTLE_ENDIAN 1234 + * #define BIG_ENDIAN 4321 + * + * And for little-endian machines, add: + * + * #define BYTE_ORDER LITTLE_ENDIAN + * + * Or for big-endian machines: + * + * #define BYTE_ORDER BIG_ENDIAN + * + * The FreeBSD machine this was written on defines BYTE_ORDER + * appropriately by including <sys/types.h> (which in turn includes + * <machine/endian.h> where the appropriate definitions are actually + * made). + */ + +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +//#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) +//#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN +//#endif + +/* + * Define the following sha2_* types to types of the correct length on + * the native archtecture. Most BSD systems and Linux define u_intXX_t + * types. Machines with very recent ANSI C headers, can use the + * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H + * during compile or in the sha.h header file. + * + * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t + * will need to define these three typedefs below (and the appropriate + * ones in sha.h too) by hand according to their system architecture. + * + * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t + * types and pointing out recent ANSI C support for uintXX_t in inttypes.h. + * + * PJ: replace by uintX_t + */ + +//typedef uint8_t sha2_byte; /* Exactly 1 byte */ +//typedef uint32_t sha2_word32; /* Exactly 4 bytes */ +//typedef uint64_t sha2_word64; /* Exactly 8 bytes */ + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +/* NOTE: Most of these are in header */ +#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) +#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) +#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) + + +/*** ENDIAN REVERSAL MACROS *******************************************/ +#if BYTE_ORDER == LITTLE_ENDIAN +#define REVERSE32(w, x) { \ + uint32_t tmp = (w); \ + tmp = (tmp >> 16) | (tmp << 16); \ + (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ +} +#define REVERSE64(w, x) { \ + uint64_t tmp = (w); \ + tmp = (tmp >> 32) | (tmp << 32); \ + tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ + ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ + (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ + ((tmp & 0x0000ffff0000ffffULL) << 16); \ +} +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +/* + * Macro for incrementally adding the unsigned 64-bit integer n to the + * unsigned 128-bit integer (represented using a two-element array of + * 64-bit words): + */ +#define ADDINC128(w,n) { \ + (w)[0] += (uint64_t)(n); \ + if ((w)[0] < (n)) { \ + (w)[1]++; \ + } \ +} + +#define MEMSET_BZERO(p,l) memset((p), 0, (l)) +#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) + +/*** THE SIX LOGICAL FUNCTIONS ****************************************/ +/* + * Bit shifting and rotation (used by the six SHA-XYZ logical functions: + * + * NOTE: The naming of R and S appears backwards here (R is a SHIFT and + * S is a ROTATION) because the SHA-256/384/512 description document + * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this + * same "backwards" definition. + */ +/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ +#define R(b,x) ((x) >> (b)) +/* 32-bit Rotate-right (used in SHA-256): */ +#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) +/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ +#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) + +/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +/* Four of six logical functions used in SHA-256: */ +#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) +#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) +#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) +#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) + +/* Four of six logical functions used in SHA-384 and SHA-512: */ +#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) +#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) +#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) +#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) + +static void sha512_last (sha512_state *state); +static void sha256_transform (sha256_state *state, const uint32_t idata[16]); +static void sha512_transform (sha512_state *state, const uint64_t idata[16]); + +/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ +/* Hash constant words K for SHA-256: */ +static const uint32_t K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* Initial hash value H for SHA-256: */ +static const uint32_t sha256_initial_hash_value[8] = { + 0x6a09e667UL, + 0xbb67ae85UL, + 0x3c6ef372UL, + 0xa54ff53aUL, + 0x510e527fUL, + 0x9b05688cUL, + 0x1f83d9abUL, + 0x5be0cd19UL +}; + +/* Hash constant words K for SHA-384 and SHA-512: */ +static const uint64_t K512[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; + +/* Initial hash value H for SHA-384 */ +static const uint64_t sha384_initial_hash_value[8] = { + 0xcbbb9d5dc1059ed8ULL, + 0x629a292a367cd507ULL, + 0x9159015a3070dd17ULL, + 0x152fecd8f70e5939ULL, + 0x67332667ffc00b31ULL, + 0x8eb44a8768581511ULL, + 0xdb0c2e0d64f98fa7ULL, + 0x47b5481dbefa4fa4ULL +}; + +/* Initial hash value H for SHA-512 */ +static const uint64_t sha512_initial_hash_value[8] = { + 0x6a09e667f3bcc908ULL, + 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, + 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, + 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, + 0x5be0cd19137e2179ULL +}; + +/*** SHA-256: *********************************************************/ +sha256_state * sha256_digest_init (sha256_state *state) +{ + MEMCPY_BCOPY(state->words, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); + MEMSET_BZERO(state->buffer, SHA256_BLOCK_LENGTH); + state->bitcount = 0; + return state; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-256 round macros: */ + +#if BYTE_ORDER == LITTLE_ENDIAN + +#define ROUND256_0_TO_15(v, a, b, c, d, e, f, g, h) \ + REVERSE32(v, W256[j]); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + W256[j]; \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)) + +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND256_0_TO_15(v, a, b, c, d, e, f, g, h) \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + (W256[j] = v); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)) + +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND256(a, b, c, d, e, f, g, h) \ + s0 = W256[(j+1)&0x0f]; \ + s0 = sigma0_256(s0); \ + s1 = W256[(j+14)&0x0f]; \ + s1 = sigma1_256(s1); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)) + +static void sha256_transform (sha256_state *state, const uint32_t idata[16]) { + uint32_t a, b, c, d, e, f, g, h, s0, s1; + uint32_t T1, *W256, v; + int j; + + W256 = state->buffer32; + + /* Initialize registers with the prev. intermediate value */ + a = state->words[0]; + b = state->words[1]; + c = state->words[2]; + d = state->words[3]; + e = state->words[4]; + f = state->words[5]; + g = state->words[6]; + h = state->words[7]; + + j = 0; + do { + /* Rounds 0 to 15 (unrolled): */ + v = idata[j]; ROUND256_0_TO_15(v, a, b, c, d, e, f, g, h); ++j; + v = idata[j]; ROUND256_0_TO_15(v, h, a, b, c, d, e, f, g); ++j; + v = idata[j]; ROUND256_0_TO_15(v, g, h, a, b, c, d, e, f); ++j; + v = idata[j]; ROUND256_0_TO_15(v, f, g, h, a, b, c, d, e); ++j; + v = idata[j]; ROUND256_0_TO_15(v, e, f, g, h, a, b, c, d); ++j; + v = idata[j]; ROUND256_0_TO_15(v, d, e, f, g, h, a, b, c); ++j; + v = idata[j]; ROUND256_0_TO_15(v, c, d, e, f, g, h, a, b); ++j; + v = idata[j]; ROUND256_0_TO_15(v, b, c, d, e, f, g, h, a); ++j; + } while (j < 16); + + /* Now for the remaining rounds to 64: */ + do { + ROUND256(a, b, c, d, e, f, g, h); ++j; + ROUND256(h, a, b, c, d, e, f, g); ++j; + ROUND256(g, h, a, b, c, d, e, f); ++j; + ROUND256(f, g, h, a, b, c, d, e); ++j; + ROUND256(e, f, g, h, a, b, c, d); ++j; + ROUND256(d, e, f, g, h, a, b, c); ++j; + ROUND256(c, d, e, f, g, h, a, b); ++j; + ROUND256(b, c, d, e, f, g, h, a); ++j; + } while (j < 64); + + /* Compute the current intermediate hash value */ + state->words[0] += a; + state->words[1] += b; + state->words[2] += c; + state->words[3] += d; + state->words[4] += e; + state->words[5] += f; + state->words[6] += g; + state->words[7] += h; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +static void sha256_transform (sha256_state *state, const uint32_t idata[16]) { + uint32_t a, b, c, d, e, f, g, h, s0, s1; + uint32_t T1, T2, *W256, v; + int j; + + W256 = state->buffer32; + + /* Initialize registers with the prev. intermediate value */ + a = state->words[0]; + b = state->words[1]; + c = state->words[2]; + d = state->words[3]; + e = state->words[4]; + f = state->words[5]; + g = state->words[6]; + h = state->words[7]; + + j = 0; + do { + v = idata[j]; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Copy data while converting to host byte order */ + REVERSE32(v, W256[j]); + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* Apply the SHA-256 compression function to update a..h with copy */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = v); +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W256[(j+1)&0x0f]; + s0 = sigma0_256(s0); + s1 = W256[(j+14)&0x0f]; + s1 = sigma1_256(s1); + + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 64); + + /* Compute the current intermediate hash value */ + state->words[0] += a; + state->words[1] += b; + state->words[2] += c; + state->words[3] += d; + state->words[4] += e; + state->words[5] += f; + state->words[6] += g; + state->words[7] += h; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +/* PJ: alignment-safe version */ + +#define data_aligned4(data) (((data - (const uint8_t *)(0UL)) & 3) == 0) +#define data_aligned8(data) (((data - (const uint8_t *)(0ULL)) & 7) == 0) + +static void sha256_transform_aligned (sha256_state *state, const uint8_t *data) { + if (data_aligned4(data)) + { + sha256_transform(state, (const uint32_t *)((const void *)data)); // alignment ok + } + else + { + uint32_t idata[16]; + memcpy(&idata[0], data, 16 * sizeof(uint32_t)); + sha256_transform(state, idata); + } +} + +void sha256_digest_add (sha256_state *state, const void *vdata, size_t len) +{ + unsigned int freespace, usedspace; + const uint8_t *data; + + if (len == 0) /* Calling with no data is valid - we do nothing */ + return; + + data = (const uint8_t *)vdata; + + usedspace = (state->bitcount >> 3) % SHA256_BLOCK_LENGTH; + if (usedspace > 0) + { + /* Calculate how much free space is available in the buffer */ + freespace = SHA256_BLOCK_LENGTH - usedspace; + + if (len >= freespace) + { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&state->buffer[usedspace], data, freespace); + state->bitcount += freespace << 3; + len -= freespace; + data += freespace; + sha256_transform(state, state->buffer32); + } + else + { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&state->buffer[usedspace], data, len); + state->bitcount += len << 3; + return; + } + } + while (len >= SHA256_BLOCK_LENGTH) + { + /* Process as many complete blocks as we can */ + sha256_transform_aligned(state, data); + + state->bitcount += SHA256_BLOCK_LENGTH << 3; + len -= SHA256_BLOCK_LENGTH; + data += SHA256_BLOCK_LENGTH; + } + if (len > 0) + { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(state->buffer, data, len); + state->bitcount += len << 3; + } +} + +static void digest_hex (uint8_t digest[], const void *data, size_t size, int flags); + +void sha256_digest_get (sha256_state *state, uint8_t digest[], int flags) { + unsigned int usedspace; + + usedspace = (state->bitcount >> 3) % SHA256_BLOCK_LENGTH; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + REVERSE64(state->bitcount,state->bitcount); +#endif + if (usedspace > 0) + { + /* Begin padding with a 1 bit: */ + state->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&state->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA256_BLOCK_LENGTH) { + MEMSET_BZERO(&state->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + sha256_transform(state, state->buffer32); + + /* And set-up for the last transform: */ + MEMSET_BZERO(state->buffer, SHA256_SHORT_BLOCK_LENGTH); + } + } + else + { + /* Set-up for the last transform: */ + MEMSET_BZERO(state->buffer, SHA256_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *state->buffer = 0x80; + } + /* Set the bit count: */ + //*(uint64_t*)&state->buffer[SHA256_SHORT_BLOCK_LENGTH] = state->bitcount; // aliasing violation warning + state->buffer64[SHA256_SHORT_BLOCK_LENGTH / sizeof(uint64_t)] = state->bitcount; + + /* Final transform: */ + sha256_transform(state, state->buffer32); + +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) + { + REVERSE32(state->words[j], state->words[j]); + } + } +#endif + if (flags & SHA_HEX) + digest_hex(digest, state->words, SHA256_DIGEST_LENGTH, flags); + else + memcpy(digest, state->words, SHA256_DIGEST_LENGTH); +} + +/*** SHA-512: *********************************************************/ +sha512_state * sha512_digest_init (sha512_state *state) +{ + MEMCPY_BCOPY(state->words, sha512_initial_hash_value, SHA512_DIGEST_LENGTH); + MEMSET_BZERO(state->buffer, SHA512_BLOCK_LENGTH); + state->bitcount[0] = 0; + state->bitcount[1] = 0; + return state; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* PJ: ++ operations moved out of macros! */ + +/* Unrolled SHA-512 round macros: */ +#if BYTE_ORDER == LITTLE_ENDIAN + +#define ROUND512_0_TO_15(v, a, b, c, d, e, f, g, h) \ + REVERSE64(v, W512[j]); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + W512[j]; \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)) + +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND512_0_TO_15(v, a, b, c, d, e, f, g, h) \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + (W512[j] = v); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)) + +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND512(a, b, c, d, e, f, g, h) \ + s0 = W512[(j+1)&0x0f]; \ + s0 = sigma0_512(s0); \ + s1 = W512[(j+14)&0x0f]; \ + s1 = sigma1_512(s1); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)) + +static void sha512_transform (sha512_state *state, const uint64_t idata[16]) +{ + uint64_t a, b, c, d, e, f, g, h, s0, s1; + uint64_t T1, *W512, v; + int j; + + W512 = state->buffer64; + + /* Initialize registers with the prev. intermediate value */ + a = state->words[0]; + b = state->words[1]; + c = state->words[2]; + d = state->words[3]; + e = state->words[4]; + f = state->words[5]; + g = state->words[6]; + h = state->words[7]; + + j = 0; + do { + v = idata[j]; ROUND512_0_TO_15(v, a, b, c, d, e, f, g, h); ++j; + v = idata[j]; ROUND512_0_TO_15(v, h, a, b, c, d, e, f, g); ++j; + v = idata[j]; ROUND512_0_TO_15(v, g, h, a, b, c, d, e, f); ++j; + v = idata[j]; ROUND512_0_TO_15(v, f, g, h, a, b, c, d, e); ++j; + v = idata[j]; ROUND512_0_TO_15(v, e, f, g, h, a, b, c, d); ++j; + v = idata[j]; ROUND512_0_TO_15(v, d, e, f, g, h, a, b, c); ++j; + v = idata[j]; ROUND512_0_TO_15(v, c, d, e, f, g, h, a, b); ++j; + v = idata[j]; ROUND512_0_TO_15(v, b, c, d, e, f, g, h, a); ++j; + } while (j < 16); + + /* Now for the remaining rounds up to 79: */ + do { + ROUND512(a, b, c, d, e, f, g, h); ++j; + ROUND512(h, a, b, c, d, e, f, g); ++j; + ROUND512(g, h, a, b, c, d, e, f); ++j; + ROUND512(f, g, h, a, b, c, d, e); ++j; + ROUND512(e, f, g, h, a, b, c, d); ++j; + ROUND512(d, e, f, g, h, a, b, c); ++j; + ROUND512(c, d, e, f, g, h, a, b); ++j; + ROUND512(b, c, d, e, f, g, h, a); ++j; + } while (j < 80); + + /* Compute the current intermediate hash value */ + state->words[0] += a; + state->words[1] += b; + state->words[2] += c; + state->words[3] += d; + state->words[4] += e; + state->words[5] += f; + state->words[6] += g; + state->words[7] += h; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +static void sha512_transform (sha512_state *state, const uint64_t idata[16]) +{ + uint64_t a, b, c, d, e, f, g, h, s0, s1; + uint64_t T1, T2, *W512, v; + int j; + + W512 = state->buffer64; + + /* Initialize registers with the prev. intermediate value */ + a = state->words[0]; + b = state->words[1]; + c = state->words[2]; + d = state->words[3]; + e = state->words[4]; + f = state->words[5]; + g = state->words[6]; + h = state->words[7]; + + j = 0; + do { + v = idata[j]; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + REVERSE64(v, W512[j]); + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* Apply the SHA-512 compression function to update a..h with copy */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = v); +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W512[(j+1)&0x0f]; + s0 = sigma0_512(s0); + s1 = W512[(j+14)&0x0f]; + s1 = sigma1_512(s1); + + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 80); + + /* Compute the current intermediate hash value */ + state->words[0] += a; + state->words[1] += b; + state->words[2] += c; + state->words[3] += d; + state->words[4] += e; + state->words[5] += f; + state->words[6] += g; + state->words[7] += h; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +static void sha512_transform_aligned (sha512_state *state, const uint8_t *data) +{ + if (data_aligned8(data)) + { + sha512_transform(state, (const uint64_t *)((const void *)data)); // alignment ok + } + else + { + uint64_t idata[16]; + memcpy(&idata[0], data, 16 * sizeof(uint64_t)); + sha512_transform(state, idata); + } +} + +void sha512_digest_add (sha512_state *state, const void *vdata, size_t len) +{ + unsigned int freespace, usedspace; + const uint8_t *data; + + if (len == 0) /* Calling with no data is valid - we do nothing */ + return; + + /* Sanity check: */ + data = (const uint8_t *)vdata; + + usedspace = (state->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; + if (usedspace > 0) + { + /* Calculate how much free space is available in the buffer */ + freespace = SHA512_BLOCK_LENGTH - usedspace; + + if (len >= freespace) + { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&state->buffer[usedspace], data, freespace); + ADDINC128(state->bitcount, freespace << 3); + len -= freespace; + data += freespace; + sha512_transform(state, state->buffer64); + } + else + { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&state->buffer[usedspace], data, len); + ADDINC128(state->bitcount, len << 3); + return; + } + } + while (len >= SHA512_BLOCK_LENGTH) + { + /* Process as many complete blocks as we can */ + sha512_transform_aligned(state, data); + + ADDINC128(state->bitcount, SHA512_BLOCK_LENGTH << 3); + len -= SHA512_BLOCK_LENGTH; + data += SHA512_BLOCK_LENGTH; + } + if (len > 0) + { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(state->buffer, data, len); + ADDINC128(state->bitcount, len << 3); + } +} + +static void sha512_last (sha512_state *state) +{ + unsigned int usedspace; + + usedspace = (state->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + REVERSE64(state->bitcount[0],state->bitcount[0]); + REVERSE64(state->bitcount[1],state->bitcount[1]); +#endif + if (usedspace > 0) + { + /* Begin padding with a 1 bit: */ + state->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&state->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA512_BLOCK_LENGTH) { + MEMSET_BZERO(&state->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + sha512_transform(state, state->buffer64); + + /* And set-up for the last transform: */ + //MEMSET_BZERO(state->buffer, SHA512_BLOCK_LENGTH - 2); // seems a typo, we overwrite last 16 bytes below + MEMSET_BZERO(state->buffer, SHA512_SHORT_BLOCK_LENGTH); + } + } + else + { + /* Prepare for final transform: */ + MEMSET_BZERO(state->buffer, SHA512_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *state->buffer = 0x80; + } + /* Store the length of input data (in bits): */ + //*(uint64_t*)&state->buffer[SHA512_SHORT_BLOCK_LENGTH] = state->bitcount[1]; // aliasing violation warning + //*(uint64_t*)&state->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = state->bitcount[0]; + state->buffer64[SHA512_SHORT_BLOCK_LENGTH / sizeof(uint64_t)] = state->bitcount[1]; + state->buffer64[SHA512_SHORT_BLOCK_LENGTH / sizeof(uint64_t) + 1] = state->bitcount[0]; + + /* Final transform: */ + sha512_transform(state, state->buffer64); +} + +void sha512_digest_get (sha512_state *state, uint8_t digest[], int flags) +{ + /* If no digest buffer is passed, we don't bother doing this: */ + sha512_last(state); + + /* Save the hash data for output: */ +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) + { + REVERSE64(state->words[j], state->words[j]); + } + } +#endif + if (flags & SHA_HEX) + digest_hex(digest, state->words, SHA512_DIGEST_LENGTH, flags); + else + memcpy(digest, state->words, SHA512_DIGEST_LENGTH); +} + +/*** SHA-384: *********************************************************/ +sha384_state * sha384_digest_init (sha384_state *state) +{ + MEMCPY_BCOPY(state->words, sha384_initial_hash_value, SHA512_DIGEST_LENGTH); + MEMSET_BZERO(state->buffer, SHA384_BLOCK_LENGTH); + state->bitcount[0] = state->bitcount[1] = 0; + return state; +} + +void sha384_digest_add (sha384_state *state, const void *data, size_t len) +{ + sha512_digest_add((sha512_state *)state, data, len); +} + +void sha384_digest_get (sha384_state *state, uint8_t digest[], int flags) +{ + sha512_last((sha512_state *)state); + + /* Save the hash data for output: */ +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 6; j++) + { + REVERSE64(state->words[j], state->words[j]); + } + } +#endif + if (flags & SHA_HEX) + digest_hex(digest, state->words, SHA384_DIGEST_LENGTH, flags); + else + memcpy(digest, state->words, SHA384_DIGEST_LENGTH); +} + +/* hex output */ + +static void digest_hex (uint8_t digest[], const void *data, size_t size, int flags) +{ + const char *alphabet; + const uint8_t *bytes; + size_t i; + + bytes = (const uint8_t *)data; + alphabet = (flags & SHA_LCHEX) ? "0123456789abcdef" : "0123456789ABCDEF"; + for (i = 0; i < size; ++i, ++bytes) + { + *digest++ = (uint8_t)alphabet[(*bytes) >> 4]; + *digest++ = (uint8_t)alphabet[(*bytes) & 15]; + } + *digest = 0; +} + +/* string checksum */ + +void sha256_digest (const void *data, size_t size, uint8_t digest[], int flags) +{ + sha256_state state; + sha256_digest_init(&state); + sha256_digest_add(&state, data, size); + sha256_digest_get(&state, digest, flags); +} + +void sha384_digest (const void *data, size_t size, uint8_t digest[], int flags) +{ + sha384_state state; + sha384_digest_init(&state); + sha384_digest_add(&state, data, size); + sha384_digest_get(&state, digest, flags); +} + +void sha512_digest (const void *data, size_t size, uint8_t digest[], int flags) +{ + sha512_state state; + sha512_digest_init(&state); + sha512_digest_add(&state, data, size); + sha512_digest_get(&state, digest, flags); +} + +/* file checksum */ + +#define DIGEST_BUFFER_SIZE 4096 + +int sha256_digest_add_file (sha256_state *state, const char *filename) +{ + FILE *fh; + uint8_t buffer[DIGEST_BUFFER_SIZE]; + size_t read; + + if ((fh = fopen(filename, "rb")) == NULL) + return 0; + do { + read = fread(buffer, 1, DIGEST_BUFFER_SIZE, fh); + sha256_digest_add(state, buffer, read); + } while (read == DIGEST_BUFFER_SIZE); + fclose(fh); + return 1; +} + +int sha256_digest_file (const char *filename, uint8_t digest[], int flags) +{ + sha256_state state; + + sha256_digest_init(&state); + if (sha256_digest_add_file(&state, filename)) + { + sha256_digest_get(&state, digest, flags); + return 1; + } + return 0; +} + +int sha384_digest_add_file (sha384_state *state, const char *filename) +{ + FILE *fh; + uint8_t buffer[DIGEST_BUFFER_SIZE]; + size_t read; + + if ((fh = fopen(filename, "rb")) == NULL) + return 0; + do { + read = fread(buffer, 1, DIGEST_BUFFER_SIZE, fh); + sha384_digest_add(state, buffer, read); + } while (read == DIGEST_BUFFER_SIZE); + fclose(fh); + return 1; +} + +int sha384_digest_file (const char *filename, uint8_t digest[], int flags) +{ + sha384_state state; + + sha384_digest_init(&state); + if (sha384_digest_add_file(&state, filename)) + { + sha384_digest_get(&state, digest, flags); + return 1; + } + return 0; +} + +int sha512_digest_add_file (sha512_state *state, const char *filename) +{ + FILE *fh; + uint8_t buffer[DIGEST_BUFFER_SIZE]; + size_t read; + + if ((fh = fopen(filename, "rb")) == NULL) + return 0; + do { + read = fread(buffer, 1, DIGEST_BUFFER_SIZE, fh); + sha512_digest_add(state, buffer, read); + } while (read == DIGEST_BUFFER_SIZE); + fclose(fh); + return 1; +} + +int sha512_digest_file (const char *filename, uint8_t digest[], int flags) +{ + sha512_state state; + + sha512_digest_init(&state); + if (sha512_digest_add_file(&state, filename)) + { + sha512_digest_get(&state, digest, flags); + return 1; + } + return 0; +} diff --git a/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilsha.h b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilsha.h new file mode 100644 index 00000000000..6c9b1bdc9c0 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/src/util/utilsha.h @@ -0,0 +1,79 @@ +/* sha2 implementation excerpted from code by Aaron D. Gifford */ + +#ifndef UTIL_SHA_H +#define UTIL_SHA_H + +#include <stddef.h> +#include <stdint.h> +#include "utildecl.h" + +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) +#define SHA384_BLOCK_LENGTH 128 +#define SHA384_DIGEST_LENGTH 48 +#define SHA384_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) + +//#define sha256_state sha256_state_t +//#define sha384_state sha384_state_t +//#define sha512_state sha512_state_t + +typedef struct { + uint32_t words[8]; + uint64_t bitcount; + union { + uint8_t buffer[SHA256_BLOCK_LENGTH]; + uint32_t buffer32[SHA256_BLOCK_LENGTH / sizeof(uint32_t)]; + uint64_t buffer64[SHA256_BLOCK_LENGTH / sizeof(uint64_t)]; + }; +} sha256_state; + +typedef struct { + uint64_t words[8]; + uint64_t bitcount[2]; + union { + uint8_t buffer[SHA512_BLOCK_LENGTH]; + uint64_t buffer64[SHA512_BLOCK_LENGTH / sizeof(uint64_t)]; + }; +} sha512_state; + +typedef sha512_state sha384_state; + +enum { + SHA_BYTES = 0, + SHA_UCHEX = (1<<0), + SHA_LCHEX = (1<<1) +}; + +#define SHA_DEFAULT SHA_BYTES +#define SHA_HEX (SHA_UCHEX|SHA_LCHEX) + +UTILAPI sha256_state * sha256_digest_init (sha256_state *state); +UTILAPI sha384_state * sha384_digest_init (sha384_state *state); +UTILAPI sha512_state * sha512_digest_init (sha512_state *state); + +UTILAPI void sha256_digest_add (sha256_state *state, const void *data, size_t size); +UTILAPI void sha384_digest_add (sha384_state *state, const void *data, size_t size); +UTILAPI void sha512_digest_add (sha512_state *state, const void *data, size_t size); + +UTILAPI void sha256_digest_get (sha256_state *state, uint8_t digest[], int flags); +UTILAPI void sha384_digest_get (sha384_state *state, uint8_t digest[], int flags); +UTILAPI void sha512_digest_get (sha512_state *state, uint8_t digest[], int flags); + +UTILAPI void sha256_digest (const void *data, size_t size, uint8_t digest[], int flags); +UTILAPI void sha384_digest (const void *data, size_t size, uint8_t digest[], int flags); +UTILAPI void sha512_digest (const void *data, size_t size, uint8_t digest[], int flags); + +UTILAPI int sha256_digest_add_file (sha256_state *state, const char *filename); +UTILAPI int sha256_digest_file (const char *filename, uint8_t digest[], int flags); + +UTILAPI int sha384_digest_add_file (sha384_state *state, const char *filename); +UTILAPI int sha384_digest_file (const char *filename, uint8_t digest[], int flags); + +UTILAPI int sha512_digest_add_file (sha512_state *state, const char *filename); +UTILAPI int sha512_digest_file (const char *filename, uint8_t digest[], int flags); + +#endif diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilarm.h b/Build/source/texk/web2c/luatexdir/luapplib/util/utilarm.h deleted file mode 100644 index ca59f9eae76..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilarm.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef UTIL_ARM_H -#define UTIL_ARM_H - -#if defined __arm__ || defined __ARM__ || defined ARM || defined __ARM || defined __arm || defined __ARM_ARCH ||defined __aarch64__ ||defined(__sparc) -# define ARM_COMPLIANT 1 -#else -# define ARM_COMPLIANT 0 -#endif - -#endif diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilmd5.c b/Build/source/texk/web2c/luatexdir/luapplib/util/utilmd5.c deleted file mode 100644 index a2926b0aa8b..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilmd5.c +++ /dev/null @@ -1,413 +0,0 @@ -/* md5 implementation by Peter Deutsch (ghost@aladdin.com) with some convenience shorthands */ - -/* begin of md5.c */ - -/* - Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.c is L. Peter Deutsch - <ghost@aladdin.com>. Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order - either statically or dynamically; added missing #include <string.h> - in library. - 2002-03-11 lpd Corrected argument list for main(), and added int return - type, in test program and T value program. - 2002-02-21 lpd Added missing #include <stdio.h> in test program. - 2000-07-03 lpd Patched to eliminate warnings about "constant is - unsigned in ANSI C, signed in traditional"; made test program - self-checking. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). - 1999-05-03 lpd Original version. - */ - -//#include "md5.h" -#include "utilmd5.h" -#include <string.h> - -#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ -#ifdef ARCH_IS_BIG_ENDIAN -# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) -#else -# define BYTE_ORDER 0 -#endif - -#define T_MASK ((uint32_t)~0) -#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) -#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) -#define T3 0x242070db -#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) -#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) -#define T6 0x4787c62a -#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) -#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) -#define T9 0x698098d8 -#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) -#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) -#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) -#define T13 0x6b901122 -#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) -#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) -#define T16 0x49b40821 -#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) -#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) -#define T19 0x265e5a51 -#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) -#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) -#define T22 0x02441453 -#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) -#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) -#define T25 0x21e1cde6 -#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) -#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) -#define T28 0x455a14ed -#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) -#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) -#define T31 0x676f02d9 -#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) -#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) -#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) -#define T35 0x6d9d6122 -#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) -#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) -#define T38 0x4bdecfa9 -#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) -#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) -#define T41 0x289b7ec6 -#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) -#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) -#define T44 0x04881d05 -#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) -#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) -#define T47 0x1fa27cf8 -#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) -#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) -#define T50 0x432aff97 -#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) -#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) -#define T53 0x655b59c3 -#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) -#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) -#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) -#define T57 0x6fa87e4f -#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) -#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) -#define T60 0x4e0811a1 -#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) -#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) -#define T63 0x2ad7d2bb -#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) - - -static void -md5_process(md5_state_t *pms, const uint8_t *data /*[64]*/) -{ - uint32_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - uint32_t t; -#if BYTE_ORDER > 0 - /* Define storage only for big-endian CPUs. */ - uint32_t X[16]; -#else - /* Define storage for little-endian or both types of CPUs. */ - uint32_t xbuf[16]; - const uint32_t *X; -#endif - - { -#if BYTE_ORDER == 0 - /* - * Determine dynamically whether this is a big-endian or - * little-endian machine, since we can use a more efficient - * algorithm on the latter. - */ - static const int w = 1; - - if (*((const uint8_t *)&w)) /* dynamic little-endian */ -#endif -#if BYTE_ORDER <= 0 /* little-endian */ - { - /* - * On little-endian machines, we can process properly aligned - * data without copying it. - */ - if (!((data - (const uint8_t *)0) & 3)) { - /* data are properly aligned */ - X = (const uint32_t *)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } - } -#endif -#if BYTE_ORDER == 0 - else /* dynamic big-endian */ -#endif -#if BYTE_ORDER >= 0 /* big-endian */ - { - /* - * On big-endian machines, we must arrange the bytes in the - * right order. - */ - const uint8_t *xp = data; - int i; - -# if BYTE_ORDER == 0 - X = xbuf; /* (dynamic only) */ -# else -# define xbuf X /* (static only) */ -# endif - for (i = 0; i < 16; ++i, xp += 4) - xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - } -#endif - } - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); -#undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); -#undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); -#undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); -#undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void -pplib_md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; - pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; - pms->abcd[3] = 0x10325476; -} - -void -md5_add(md5_state_t *pms, const void *input, size_t size) -{ - const uint8_t *p = (const uint8_t *)input; - int nbytes = (int)size; // PJ - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - uint32_t nbits = (uint32_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - pms->count[1]++; - - /* Process an initial partial block. */ - if (offset) { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -void -md5_put(md5_state_t *pms, uint8_t digest[16]) -{ - static const uint8_t pad[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - uint8_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (uint8_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_add(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_add(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (uint8_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} - -/* end of md5.h */ - -static md5_state_t state; - -void pplib_md5 (const void *input, size_t length, uint8_t output[16]) -{ - pplib_md5_init(&state); - md5_add(&state, input, length); - md5_put(&state, output); -} - -void md5init (void) -{ - pplib_md5_init(&state); -} - -void md5add (const void *input, size_t length) -{ - md5_add(&state, input, length); -} - -void md5put (uint8_t output[16]) -{ - md5_put(&state, output); -} diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilmd5.c.orig b/Build/source/texk/web2c/luatexdir/luapplib/util/utilmd5.c.orig deleted file mode 100644 index 06fb03c5bce..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilmd5.c.orig +++ /dev/null @@ -1,413 +0,0 @@ -/* md5 implementation by Peter Deutsch (ghost@aladdin.com) with some convenience shorthands */ - -/* begin of md5.c */ - -/* - Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.c is L. Peter Deutsch - <ghost@aladdin.com>. Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order - either statically or dynamically; added missing #include <string.h> - in library. - 2002-03-11 lpd Corrected argument list for main(), and added int return - type, in test program and T value program. - 2002-02-21 lpd Added missing #include <stdio.h> in test program. - 2000-07-03 lpd Patched to eliminate warnings about "constant is - unsigned in ANSI C, signed in traditional"; made test program - self-checking. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). - 1999-05-03 lpd Original version. - */ - -//#include "md5.h" -#include "utilmd5.h" -#include <string.h> - -#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ -#ifdef ARCH_IS_BIG_ENDIAN -# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) -#else -# define BYTE_ORDER 0 -#endif - -#define T_MASK ((uint32_t)~0) -#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) -#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) -#define T3 0x242070db -#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) -#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) -#define T6 0x4787c62a -#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) -#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) -#define T9 0x698098d8 -#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) -#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) -#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) -#define T13 0x6b901122 -#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) -#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) -#define T16 0x49b40821 -#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) -#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) -#define T19 0x265e5a51 -#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) -#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) -#define T22 0x02441453 -#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) -#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) -#define T25 0x21e1cde6 -#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) -#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) -#define T28 0x455a14ed -#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) -#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) -#define T31 0x676f02d9 -#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) -#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) -#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) -#define T35 0x6d9d6122 -#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) -#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) -#define T38 0x4bdecfa9 -#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) -#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) -#define T41 0x289b7ec6 -#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) -#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) -#define T44 0x04881d05 -#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) -#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) -#define T47 0x1fa27cf8 -#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) -#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) -#define T50 0x432aff97 -#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) -#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) -#define T53 0x655b59c3 -#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) -#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) -#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) -#define T57 0x6fa87e4f -#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) -#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) -#define T60 0x4e0811a1 -#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) -#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) -#define T63 0x2ad7d2bb -#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) - - -static void -md5_process(md5_state_t *pms, const uint8_t *data /*[64]*/) -{ - uint32_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - uint32_t t; -#if BYTE_ORDER > 0 - /* Define storage only for big-endian CPUs. */ - uint32_t X[16]; -#else - /* Define storage for little-endian or both types of CPUs. */ - uint32_t xbuf[16]; - const uint32_t *X; -#endif - - { -#if BYTE_ORDER == 0 - /* - * Determine dynamically whether this is a big-endian or - * little-endian machine, since we can use a more efficient - * algorithm on the latter. - */ - static const int w = 1; - - if (*((const uint8_t *)&w)) /* dynamic little-endian */ -#endif -#if BYTE_ORDER <= 0 /* little-endian */ - { - /* - * On little-endian machines, we can process properly aligned - * data without copying it. - */ - if (!((data - (const uint8_t *)0) & 3)) { - /* data are properly aligned */ - X = (const uint32_t *)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } - } -#endif -#if BYTE_ORDER == 0 - else /* dynamic big-endian */ -#endif -#if BYTE_ORDER >= 0 /* big-endian */ - { - /* - * On big-endian machines, we must arrange the bytes in the - * right order. - */ - const uint8_t *xp = data; - int i; - -# if BYTE_ORDER == 0 - X = xbuf; /* (dynamic only) */ -# else -# define xbuf X /* (static only) */ -# endif - for (i = 0; i < 16; ++i, xp += 4) - xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - } -#endif - } - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); -#undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); -#undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); -#undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); -#undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void -md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; - pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; - pms->abcd[3] = 0x10325476; -} - -void -md5_add(md5_state_t *pms, const void *input, size_t size) -{ - const uint8_t *p = (const uint8_t *)input; - int nbytes = (int)size; // PJ - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - uint32_t nbits = (uint32_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - pms->count[1]++; - - /* Process an initial partial block. */ - if (offset) { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -void -md5_put(md5_state_t *pms, uint8_t digest[16]) -{ - static const uint8_t pad[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - uint8_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (uint8_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_add(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_add(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (uint8_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} - -/* end of md5.h */ - -static md5_state_t state; - -void md5 (const void *input, size_t length, uint8_t output[16]) -{ - md5_init(&state); - md5_add(&state, input, length); - md5_put(&state, output); -} - -void md5init (void) -{ - md5_init(&state); -} - -void md5add (const void *input, size_t length) -{ - md5_add(&state, input, length); -} - -void md5put (uint8_t output[16]) -{ - md5_put(&state, output); -} diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilmd5.h b/Build/source/texk/web2c/luatexdir/luapplib/util/utilmd5.h deleted file mode 100644 index 2fb4bc58de7..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilmd5.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef UTIL_MD5_H -#define UTIL_MD5_H - -#include <stdint.h> // for uintX8_t -#include <stddef.h> // for size_t -#include "utildecl.h" - -/* begin of md5.h */ - -/* - Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.h is L. Peter Deutsch - <ghost@aladdin.com>. Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Removed support for non-ANSI compilers; removed - references to Ghostscript; clarified derivation from RFC 1321; - now handles byte order either statically or dynamically. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke <purschke@bnl.gov>. - 1999-05-03 lpd Original version. - */ - -//#ifndef md5_INCLUDED -//# define md5_INCLUDED - -/* - * This package supports both compile-time and run-time determination of CPU - * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be - * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is - * defined as non-zero, the code will be compiled to run only on big-endian - * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to - * run on either big- or little-endian CPUs, but will run slightly less - * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. - */ - -// PJ: replaced with uint8_t and uint32_t -//typedef unsigned char md5_byte_t; /* 8-bit byte */ -//typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - uint32_t count[2]; /* message length in bits, lsw first */ - uint32_t abcd[4]; /* digest buffer */ - uint8_t buf[64]; /* accumulate block */ -} md5_state_t; - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Initialize the algorithm. */ -UTILAPI void pplib_md5_init (md5_state_t *pms); - -/* Append a string to the message. */ -//void md5_add(md5_state_t *pms, const uint8_t *data, int nbytes); // PJ -UTILAPI void md5_add (md5_state_t *pms, const void *input, size_t size); - -/* Finish the message and return the digest. */ -//void md5_finish(md5_state_t *pms, uint8_t digest[16]); // PJ -UTILAPI void md5_put (md5_state_t *pms, uint8_t digest[16]); - -#ifdef __cplusplus -} /* end extern "C" */ -#endif - -//#endif /* md5_INCLUDED */ - -/* end of md5.h */ - -#define md5_state md5_state_t - -UTILAPI void md5init (void); -UTILAPI void md5add (const void *input, size_t length); -UTILAPI void md5put (uint8_t output[16]); - -UTILAPI void pplib_md5 (const void *input, size_t length, uint8_t output[16]); - -#endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilmd5.h.orig b/Build/source/texk/web2c/luatexdir/luapplib/util/utilmd5.h.orig deleted file mode 100644 index c4eecff4f75..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilmd5.h.orig +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef UTIL_MD5_H -#define UTIL_MD5_H - -#include <stdint.h> // for uintX8_t -#include <stddef.h> // for size_t -#include "utildecl.h" - -/* begin of md5.h */ - -/* - Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.h is L. Peter Deutsch - <ghost@aladdin.com>. Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Removed support for non-ANSI compilers; removed - references to Ghostscript; clarified derivation from RFC 1321; - now handles byte order either statically or dynamically. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke <purschke@bnl.gov>. - 1999-05-03 lpd Original version. - */ - -//#ifndef md5_INCLUDED -//# define md5_INCLUDED - -/* - * This package supports both compile-time and run-time determination of CPU - * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be - * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is - * defined as non-zero, the code will be compiled to run only on big-endian - * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to - * run on either big- or little-endian CPUs, but will run slightly less - * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. - */ - -// PJ: replaced with uint8_t and uint32_t -//typedef unsigned char md5_byte_t; /* 8-bit byte */ -//typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - uint32_t count[2]; /* message length in bits, lsw first */ - uint32_t abcd[4]; /* digest buffer */ - uint8_t buf[64]; /* accumulate block */ -} md5_state_t; - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Initialize the algorithm. */ -UTILAPI void md5_init (md5_state_t *pms); - -/* Append a string to the message. */ -//void md5_add(md5_state_t *pms, const uint8_t *data, int nbytes); // PJ -UTILAPI void md5_add (md5_state_t *pms, const void *input, size_t size); - -/* Finish the message and return the digest. */ -//void md5_finish(md5_state_t *pms, uint8_t digest[16]); // PJ -UTILAPI void md5_put (md5_state_t *pms, uint8_t digest[16]); - -#ifdef __cplusplus -} /* end extern "C" */ -#endif - -//#endif /* md5_INCLUDED */ - -/* end of md5.h */ - -#define md5_state md5_state_t - -UTILAPI void md5init (void); -UTILAPI void md5add (const void *input, size_t length); -UTILAPI void md5put (uint8_t output[16]); - -UTILAPI void md5 (const void *input, size_t length, uint8_t output[16]); - -#endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilmem.h b/Build/source/texk/web2c/luatexdir/luapplib/util/utilmem.h deleted file mode 100644 index e2d1286187b..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilmem.h +++ /dev/null @@ -1,59 +0,0 @@ - -#ifndef UTIL_MEM_H -#define UTIL_MEM_H - -#include <stdlib.h> // for size_t and alloc functions -#include "utildecl.h" - -UTILAPI void * util_malloc (size_t size); -UTILAPI void * util_calloc (size_t num, size_t size); -UTILAPI void * util_realloc (void *m, size_t size); - -#define util_free free // not a call - -/* arrays */ - -#define array_header(element_type, integer_type) \ - element_type *data; integer_type size; integer_type space - -#define array_of(element_type) array_header(element_type, size_t) - -#define array_data_is_allocated(array) ((array)->data != (void *)((array) + 1)) - -#define array_create(array, array_type, element_type, init) \ - (array = (array_type *)util_malloc(sizeof(array_type) + ((init) > 0 ? ((init) * sizeof(element_type)) : 1)), \ - array_init(array, element_type, init)) - -#define array_init(array, element_type, init) \ - ((array)->data = (element_type *)((array) + 1), (array)->size = 0, (array)->space = init) - -#define array_init_data(array, element_type, init) \ - ((array)->data = (element_type *)util_malloc((init) * sizeof(element_type)), (array)->size = 0, (array)->space = init) - -#define array_free_data(array) \ - ((void)(array_data_is_allocated(array) && (util_free((array)->data), 0))) - -#define array_free(array) \ - ((void)(array_free_data(array), (util_free(array), 0))) - -void util_resize (void **data, size_t unit, size_t size, size_t extra, size_t *space, int allocated); - -#define array_ensure(array, unit, extra) \ - ((void)((array)->size + (extra) > (array)->space && \ - (util_resize((void **)(&(array)->data), unit, (array)->size, extra, &(array)->space, array_data_is_allocated(array)), 0))) - -#define array_ensure_alloc(array, unit, extra, isalloc) \ - ((void)((array)->size + (extra) > (array)->space && \ - (util_resize((void **)(&(array)->data), unit, (array)->size, extra, &(array)->space, isalloc), 0))) - -#define array_at(array, index) ((array)->data + index) -#define array_index(array, index) (index < (array)->size ? array_at(array, index) : NULL) -#define array_top(array) ((array)->data + (array)->size - 1) - -#define array_from_bottom(array, index) array_at(array, index - 1) -#define array_from_top(array, negindex) array_at(array, (array)->size + (negindex)) - -#define array_push(array) ((array)->data + ((array)->size)++) -#define array_pop(array) ((array)->data + --((array)->size)) - -#endif diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilnumber.h b/Build/source/texk/web2c/luatexdir/luapplib/util/utilnumber.h deleted file mode 100644 index 3c96571b5ce..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilnumber.h +++ /dev/null @@ -1,354 +0,0 @@ -#ifndef UTIL_NUMBER_H -#define UTIL_NUMBER_H - -#include <stddef.h> // for size_t - -#include "utilplat.h" -#include "utildecl.h" - -/* since 'long' isn't long for msvc64/mingw64, we need a type for machine word */ - -#if !defined(__cplusplus) || !defined(_MSC_VER) -# include <stdint.h> // int*_t types are in standard in msvc++ -#endif - -//#if defined(MSVC64) || defined(__MINGW64__) || defined(__x86_64__) || UINTPTR_MAX > 0xffffffff -//# define BIT64 -//#else -//# define BIT64 -//#endif - -#if defined(_WIN64) || defined(__MINGW32__) -# define INT64F "%I64d" -# define UINT64F "%I64u" -#else -# define INT64F "%lld" -# define UINT64F "%llu" -#endif - -#if defined(MSVC64) -# define intlw_t int64_t -# define uintlw_t uint64_t -# define INTLW(N) N##I64 -# define UINTLW(N) N##UI64 -# define INTLWF INT64F -# define UINTLWF UINT64F -#elif defined(__MINGW64__) -# define intlw_t int64_t -# define uintlw_t uint64_t -# define INTLW(N) N##LL -# define UINTLW(N) N##ULL -# define INTLWF INT64F -# define UINTLWF UINT64F -#else // 32bit or sane 64bit (LP64) -# define intlw_t long -# define uintlw_t size_t /*unsigned long*/ -# define INTLW(N) N##L -# define UINTLW(N) N##UL -# define INTLWF "%ld" -# define UINTLWF "%lu" -#endif - -/* basic constants */ - -#define MAX_RADIX 36 -// #define MAX_INTEGER_DIGITS 65 /* 64-bit number in binary form plus '\0' */ -#define MAX_INTEGER_DIGITS 128 // to handle romannumeral of short int - -#define base36_uc_alphabet "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" -#define base36_lc_alphabet "0123456789abcdefghijklmnopqrstuvwxyz" - -#define base26_uc_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -#define base26_lc_alphabet "abcdefghijklmnopqrstuvwxyz" -extern const int base26_lookup[]; - -#define base36_lc_palindrome "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" -#define base36_uc_palindrome "ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - -extern const int base36_lookup[]; - -#define base10_palindrome "9876543210123456789" -#define base10_alphabet "0123456789" -extern const int base10_lookup[]; - -#define base16_uc_alphabet "0123456789ABCDEF" -#define base16_lc_alphabet "0123456789abcdef" -extern const int base16_lookup[]; - -#define base16_uc_digit1(c) base16_uc_alphabet[(c)>>4] -#define base16_uc_digit2(c) base16_uc_alphabet[(c)&15] -#define base16_lc_digit1(c) base16_lc_alphabet[(c)>>4] -#define base16_lc_digit2(c) base16_lc_alphabet[(c)&15] - -#define base8_digit(c) ((unsigned)(c - '0') <= (unsigned)('7' - '0')) -#define base8_value(c) (base8_digit(c) ? (c) - '0' : -1) - -#define base10_digit(c) ((unsigned)(c - '0') <= (unsigned)('9' - '0')) -#define base10_value(c) (base10_lookup[(uint8_t)c]) - -#define base16_digit(c) (base16_lookup[(uint8_t)c] >= 0) -#define base16_value(c) (base16_lookup[(uint8_t)c]) - -#define base26_digit(c) (base26_lookup[(uint8_t)c] >= 0) -#define base26_value(c) (base26_lookup[(uint8_t)c]) - -#define base36_digit(c) (base36_lookup[(uint8_t)c] >= 0) -#define base36_value(c) (base36_lookup[(uint8_t)c]) - -//#define base_digit(c, radix) ((unsigned)(base36_lookup[c]) < (unsigned)(radix)) -//#define base_value(c, radix) (base_digit(c, radix) ? base36_lookup[c] : -1) - -/* integer from string; return a pointer to character next to the last digit */ - -UTILAPI const char * string_to_int32 (const char *s, int32_t *number); -UTILAPI const char * string_to_intlw (const char *s, intlw_t *number); -UTILAPI const char * string_to_int64 (const char *s, int64_t *number); - -UTILAPI const char * string_to_uint32 (const char *s, uint32_t *number); -UTILAPI const char * string_to_uintlw (const char *s, uintlw_t *number); -UTILAPI const char * string_to_uint64 (const char *s, uint64_t *number); - -UTILAPI const char * radix_to_int32 (const char *s, int32_t *number, int radix); -UTILAPI const char * radix_to_intlw (const char *s, intlw_t *number, int radix); -UTILAPI const char * radix_to_int64 (const char *s, int64_t *number, int radix); - -UTILAPI const char * radix_to_uint32 (const char *s, uint32_t *number, int radix); -UTILAPI const char * radix_to_uintlw (const char *s, uintlw_t *number, int radix); -UTILAPI const char * radix_to_uint64 (const char *s, uint64_t *number, int radix); - -UTILAPI const char * roman_to_uint16 (const char *s, uint16_t *number); - -UTILAPI const char * alpha_to_uint32 (const char *s, uint32_t *number); -UTILAPI const char * alpha_to_uintlw (const char *s, uintlw_t *number); -UTILAPI const char * alpha_to_uint64 (const char *s, uint64_t *number); - -UTILAPI const char * alphan_to_uint32 (const char *s, uint32_t *number); -UTILAPI const char * alphan_to_uintlw (const char *s, uintlw_t *number); -UTILAPI const char * alphan_to_uint64 (const char *s, uintlw_t *number); - -/* -integer to string; return a pointer to null-terminated static const string -same but also stores pointer to trailing null (to be used for firther formatting) -*/ - -UTILAPI char * int32_as_string (int32_t number, char **e); -UTILAPI char * intlw_as_string (intlw_t number, char **e); -UTILAPI char * int64_as_string (int64_t number, char **e); - -UTILAPI char * uint32_as_string (uint32_t number, char **e); -UTILAPI char * uintlw_as_string (uintlw_t number, char **e); -UTILAPI char * uint64_as_string (uint64_t number, char **e); - -#define int32_to_string(number) int32_as_string(number, NULL) -#define intlw_to_string(number) intlw_as_string(number, NULL) -#define int64_to_string(number) int64_as_string(number, NULL) - -#define uint32_to_string(number) uint32_as_string(number, NULL) -#define uintlw_to_string(number) uintlw_as_string(number, NULL) -#define uint64_to_string(number) uint64_as_string(number, NULL) - -UTILAPI char * int32_as_radix (int32_t number, int radix, char **e); -UTILAPI char * intlw_as_radix (intlw_t number, int radix, char **e); -UTILAPI char * int64_as_radix (int64_t number, int radix, char **e); - -UTILAPI char * uint32_as_radix (uint32_t number, int radix, char **e); -UTILAPI char * uintlw_as_radix (uintlw_t number, int radix, char **e); -UTILAPI char * uint64_as_radix (uint64_t number, int radix, char **e); - -#define int32_to_radix(number, radix) int32_as_radix(number, radix, NULL) -#define intlw_to_radix(number, radix) intlw_as_radix(number, radix, NULL) -#define int64_to_radix(number, radix) int64_as_radix(number, radix, NULL) - -#define uint32_to_radix(number, radix) uint32_as_radix(number, radix, NULL) -#define uintlw_to_radix(number, radix) uintlw_as_radix(number, radix, NULL) -#define uint64_to_radix(number, radix) uint64_as_radix(number, radix, NULL) - -UTILAPI char * uint32_as_alpha_uc (uint32_t number, char **e); -UTILAPI char * uint32_as_alpha_lc (uint32_t number, char **e); -UTILAPI char * uintlw_as_alpha_uc (uintlw_t number, char **e); -UTILAPI char * uintlw_as_alpha_lc (uintlw_t number, char **e); -UTILAPI char * uint64_as_alpha_uc (uint64_t number, char **e); -UTILAPI char * uint64_as_alpha_lc (uint64_t number, char **e); - -#define uint32_to_alpha_uc(number) uint32_as_alpha_uc(number, NULL) -#define uint32_to_alpha_lc(number) uint32_as_alpha_lc(number, NULL) -#define uintlw_to_alpha_uc(number) uintlw_as_alpha_uc(number, NULL) -#define uintlw_to_alpha_lc(number) uintlw_as_alpha_lc(number, NULL) -#define uint64_to_alpha_uc(number) uint64_as_alpha_uc(number, NULL) -#define uint64_to_alpha_lc(number) uint64_as_alpha_lc(number, NULL) - -UTILAPI char * uint32_as_alphan_uc (uint32_t number, char **e); -UTILAPI char * uint32_as_alphan_lc (uint32_t number, char **e); -UTILAPI char * uintlw_as_alphan_uc (uintlw_t number, char **e); -UTILAPI char * uintlw_as_alphan_lc (uintlw_t number, char **e); -UTILAPI char * uint64_as_alphan_uc (uint64_t number, char **e); -UTILAPI char * uint64_as_alphan_lc (uint64_t number, char **e); - -#define uint32_to_alphan_uc(number) uint32_as_alpha_uc(number, NULL) -#define uint32_to_alphan_lc(number) uint32_as_alpha_lc(number, NULL) -#define uintlw_to_alphan_uc(number) uintlw_as_alpha_uc(number, NULL) -#define uintlw_to_alphan_lc(number) uintlw_as_alpha_lc(number, NULL) -#define uint64_to_alphan_uc(number) uint64_as_alpha_uc(number, NULL) -#define uint64_to_alphan_lc(number) uint64_as_alpha_lc(number, NULL) - -/* roman numeral (limited to uint16_t) */ - -UTILAPI char * uint16_as_roman_uc (uint16_t number, char **e); -UTILAPI char * uint16_as_roman_lc (uint16_t number, char **e); - -#define uint16_to_roman_uc(number) uint16_as_roman_uc(number, NULL) -#define uint16_to_roman_lc(number) uint16_as_roman_lc(number, NULL) - -#define uint16_as_roman(number) uint16_as_roman_uc(number) -#define uint16_to_roman(number) uint16_to_roman_uc(number) - -/* double/float to string */ - -UTILAPI char * double_to_string (double number, int digits); -UTILAPI char * float_to_string (float number, int digits); - -UTILAPI char * double_as_string (double number, int digits, char **r, char **e); -UTILAPI char * float_as_string (float number, int digits, char **r, char **e); - -/* string to double/float */ - -UTILAPI const char * string_to_double (const char *s, double *number); -UTILAPI const char * string_to_float (const char *s, float *number); - -/* convenience form accepting comma among a dot, with not exp notation (eg. pdf) */ - -UTILAPI const char * convert_to_double (const char *s, double *number); -UTILAPI const char * convert_to_float (const char *s, float *number); - -/* binary data parsers helpers */ - -#define get_byte1(i) ((i)&255) -#define get_byte2(i) (((i)>>8)&255) -#define get_byte3(i) (((i)>>16)&255) -#define get_byte4(i) (((i)>>24)&255) - -#define read_uint16be_as(s, int_type) ((int_type)((s[0]<<8)|s[1])) -#define read_uint32be_as(s, int_type) ((int_type)((s[0]<<24)|(s[1]<<16)|(s[2]<<8)|s[3])) - -#define read_uint16le_as(s, int_type) ((int_type)((s[1]<<8)|s[0])) -#define read_uint32le_as(s, int_type) ((int_type)((s[3]<<24)|(s[2]<<16)|(s[1]<<8)|s[0])) - -#define read_uint16_native(s) (*((uint16_t *)(s))) -#define read_uint32_native(s) (*((uint32_t *)(s))) -#define read_int16_native(s) (*((int16_t *)(s))) -#define read_int32_native(s) (*((int32_t *)(s))) - -#define scan_uint16be_as(s, int_type) (s += 2, (int_type)((s[-2]<<8)|s[-1])) -#define scan_uint32be_as(s, int_type) (s += 4, (int_type)((s[-4]<<24)|(s[-3]<<16)|(s[-2]<<8)|s[-1])) - -#define scan_uint16le_as(s, int_type) (s += 2, (int_type)((s[-1]<<8)|s[-2])) -#define scan_uint32le_as(s, int_type) (s += 4, (int_type)((s[-1]<<24)|(s[-2]<<16)|(s[-3]<<8)|s[-4])) - -#define scan_uint16_native(s) (s += 2, read_uint16_native(s-2)) -#define scan_uint32_native(s) (s += 4, read_uint32_native(s-4)) -#define scan_int16_native(s) (s += 2, read_int16_native(s-2)) -#define scan_int32_native(s) (s += 4, read_int32_native(s-4)) - -#define read_fixed16_16_as(s, float_type) (((float_type)read_uint32be_as(s, signed int))/(1<<16)) -#define read_fixed2_14_as(s, float_type) (((float_type)read_uint16be_as(s, signed short))/(1<<14)) - -#define scan_fixed16_16_as(s, float_type) (((float_type)scan_uint32be_as(s, signed int))/(1<<16)) -#define scan_fixed2_14_as(s, float_type) (((float_type)scan_uint16be_as(s, signed short))/(1<<14)) - -/* internal procedures */ - -#define _scan_sign(c, sign, next) \ - do { if (c == '-') { sign = 1; c = next; } else if (c == '+') { sign = 0; c = next; } else sign = 0; } while (0) - -#define integer_multiplied10(number) (((number) << 1) + ((number) << 3)) - -#define _scan_integer(c, number, next) \ - for (number = 0; base10_digit(c); number = integer_multiplied10(number) + (c - '0'), c = next) -#define _scan_radix(c, number, radix, next) \ - for (number = 0; (c = base36_value(c)) >= 0 && c < radix; number = number * radix + c, c = next) - -#define _read_integer(c, number, next) \ - for (number = c - '0', c = next; base10_digit(c); number = integer_multiplied10(number) + (c - '0'), c = next) -#define _read_radix(c, number, radix, next) \ - for (number = c - '0', c = next; (c = base36_value(c)) >= 0 && c < radix; number = number * radix + c, c = next) - -/* rationals */ - -#define _scan_decimal(c, number, next) \ - for (number = 0; base10_digit(c); number = number*10 + (c - '0'), c = next) -#define _scan_fraction(c, number, exponent10, next) \ - for (exponent10 = 0; base10_digit(c); --exponent10, number = number*10 + (c - '0'), c = next) - -#define _scan_exponent10(c, exponent10, next) \ - do { \ - int eexponent10, eexpsign; \ - _scan_sign(c, eexpsign, next); \ - _scan_integer(c, eexponent10, next); \ - if (eexpsign) \ - exponent10 -= eexponent10; \ - else \ - exponent10 += eexponent10; \ - } while(0) - -#if 0 - -// kept just for sentiment ;) - -extern const double double_binary_power10[]; -extern const float float_binary_power10[]; -extern const double double_binary_negpower10[]; -extern const float float_binary_negpower10[]; - -#define double_negative_exp10(number, exponent) \ -{ const double *bp10; int e = ((exponent) < 511 ? 511 : -(exponent)); \ - for (bp10 = double_binary_negpower10; e > 0; e >>= 1, ++bp10) \ - if (e & 1) number *= *bp10; } - -#define float_negative_exp10(number, exponent) \ -{ const float *bp10; int e = ((exponent) < 64 ? 64 : -(exponent)); \ - for (bp10 = float_binary_negpower10; e > 0; e >>= 1, ++bp10) \ - if (e & 1) number *= *bp10; } - -#define double_positive_exp10(number, exponent) \ -{ const double *bp10; int e = ((exponent) > 511 ? 511 : (exponent)); \ - for (bp10 = double_binary_power10; e > 0; e >>= 1, ++bp10) \ - if (e & 1) number *= *bp10; } - -#define float_positive_exp10(number, exponent) \ -{ const float *bp10; int e = ((exponent) > 64 ? 64 : (exponent)); \ - for (bp10 = double_binary_power10; e > 0; e >>= 1, ++bp10) \ - if (e & 1) number *= *bp10; } - -#define double_exp10(number, exponent) \ - if ((exponent) < 0) double_negative_exp10(number, exponent) else if ((exponent) > 0) double_positive_exp10(number, exponent) - -#define float_exp10(number, exponent) \ - if ((exponent) < 0) float_negative_exp10(number, exponent) else if ((exponent) > 0) float_positive_exp10(number, exponent) - -#else - -extern const double double_decimal_power10[]; -extern const float float_decimal_power10[]; -extern const double double_decimal_negpower10[]; -extern const float float_decimal_negpower10[]; - -#define double_negative_exp10(number, exponent) ((number) *= double_decimal_negpower10[(exponent) < -308 ? 308 : -(exponent)]) -#define double_positive_exp10(number, exponent) ((number) *= double_decimal_power10[(exponent) > 308 ? 308 : (exponent)]) - -#define float_negative_exp10(number, exponent) ((number) *= float_decimal_negpower10[(exponent) < -38 ? 38 : -(exponent)]) -#define float_positive_exp10(number, exponent) ((number) *= float_decimal_power10[(exponent) > 38 ? 38 : (exponent)]) - -#define double_exp10(number, exponent) ((void)(((exponent) < 0 && double_negative_exp10(number, exponent)) || (((exponent) > 0 && double_positive_exp10(number, exponent))))) -#define float_exp10(number, exponent) ((void)(((exponent) < 0 && float_negative_exp10(number, exponent)) || (((exponent) > 0 && float_positive_exp10(number, exponent))))) - -#endif - -/* pretty common stuff */ - -#define bytes_to_hex(input, size, output) bytes_to_hex_lc(input, size, output) -UTILAPI size_t bytes_to_hex_lc (const void *input, size_t size, uint8_t *output); -UTILAPI size_t bytes_to_hex_uc (const void *input, size_t size, uint8_t *output); -UTILAPI size_t hex_to_bytes (const void *input, size_t size, uint8_t *output); -UTILAPI void print_as_hex (const void *input, size_t bytes); - -#endif
\ No newline at end of file diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilsha.c b/Build/source/texk/web2c/luatexdir/luapplib/util/utilsha.c deleted file mode 100644 index 2b44e40bec7..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilsha.c +++ /dev/null @@ -1,1287 +0,0 @@ -/* sha2 implementation by Aaron D. Gifford (http://www.aarongifford.com) */ - -#include "utilarm.h" - -#if ARM_COMPLIANT -#include <stdlib.h> -#endif - -#ifndef BYTE_ORDER -#define BYTE_ORDER LITTLE_ENDIAN -#endif -/* begin of sha2.c */ - -/* - * FILE: sha2.c - * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ - * - * Copyright (c) 2000-2001, Aaron D. Gifford - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ - */ - -#include <string.h> /* memcpy()/memset() or bcopy()/bzero() */ -#include <assert.h> /* assert() */ -//#include "sha2.h" -#include "utilsha.h" - -/* - * ASSERT NOTE: - * Some sanity checking code is included using assert(). On my FreeBSD - * system, this additional code can be removed by compiling with NDEBUG - * defined. Check your own systems manpage on assert() to see how to - * compile WITHOUT the sanity checking code on your system. - * - * UNROLLED TRANSFORM LOOP NOTE: - * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform - * loop version for the hash transform rounds (defined using macros - * later in this file). Either define on the command line, for example: - * - * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c - * - * or define below: - * - * #define SHA2_UNROLL_TRANSFORM - * - */ - - -/*** SHA-256/384/512 Machine Architecture Definitions *****************/ -/* - * BYTE_ORDER NOTE: - * - * Please make sure that your system defines BYTE_ORDER. If your - * architecture is little-endian, make sure it also defines - * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are - * equivilent. - * - * If your system does not define the above, then you can do so by - * hand like this: - * - * #define LITTLE_ENDIAN 1234 - * #define BIG_ENDIAN 4321 - * - * And for little-endian machines, add: - * - * #define BYTE_ORDER LITTLE_ENDIAN - * - * Or for big-endian machines: - * - * #define BYTE_ORDER BIG_ENDIAN - * - * The FreeBSD machine this was written on defines BYTE_ORDER - * appropriately by including <sys/types.h> (which in turn includes - * <machine/endian.h> where the appropriate definitions are actually - * made). - */ -#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) -#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN -#endif - -/* - * Define the followingsha2_* types to types of the correct length on - * the native archtecture. Most BSD systems and Linux define u_intXX_t - * types. Machines with very recent ANSI C headers, can use the - * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H - * during compile or in the sha.h header file. - * - * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t - * will need to define these three typedefs below (and the appropriate - * ones in sha.h too) by hand according to their system architecture. - * - * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t - * types and pointing out recent ANSI C support for uintXX_t in inttypes.h. - * - * PJ: replace by uintX_t - */ - -//typedef uint8_t sha2_byte; /* Exactly 1 byte */ -//typedef uint32_t sha2_word32; /* Exactly 4 bytes */ -//typedef uint64_t sha2_word64; /* Exactly 8 bytes */ - -/*** SHA-256/384/512 Various Length Definitions ***********************/ -/* NOTE: Most of these are in sha2.h */ -#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) -#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) -#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) - - -/*** ENDIAN REVERSAL MACROS *******************************************/ -#if BYTE_ORDER == LITTLE_ENDIAN -#define REVERSE32(w,x) { \ - uint32_t tmp = (w); \ - tmp = (tmp >> 16) | (tmp << 16); \ - (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ -} -#define REVERSE64(w,x) { \ - uint64_t tmp = (w); \ - tmp = (tmp >> 32) | (tmp << 32); \ - tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ - ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ - (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ - ((tmp & 0x0000ffff0000ffffULL) << 16); \ -} -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -/* - * Macro for incrementally adding the unsigned 64-bit integer n to the - * unsigned 128-bit integer (represented using a two-element array of - * 64-bit words): - */ -#define ADDINC128(w,n) { \ - (w)[0] += (uint64_t)(n); \ - if ((w)[0] < (n)) { \ - (w)[1]++; \ - } \ -} - -/* - * Macros for copying blocks of memory and for zeroing out ranges - * of memory. Using these macros makes it easy to switch from - * using memset()/memcpy() and using bzero()/bcopy(). - * - * Please define either SHA2_USE_MEMSET_MEMCPY or define - * SHA2_USE_BZERO_BCOPY depending on which function set you - * choose to use: - */ -#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) -/* Default to memset()/memcpy() if no option is specified */ -#define SHA2_USE_MEMSET_MEMCPY 1 -#endif -#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) -/* Abort with an error if BOTH options are defined */ -#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! -#endif - -#ifdef SHA2_USE_MEMSET_MEMCPY -#define MEMSET_BZERO(p,l) memset((p), 0, (l)) -#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) -#endif -#ifdef SHA2_USE_BZERO_BCOPY -#define MEMSET_BZERO(p,l) bzero((p), (l)) -#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) -#endif - - -/*** THE SIX LOGICAL FUNCTIONS ****************************************/ -/* - * Bit shifting and rotation (used by the six SHA-XYZ logical functions: - * - * NOTE: The naming of R and S appears backwards here (R is a SHIFT and - * S is a ROTATION) because the SHA-256/384/512 description document - * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this - * same "backwards" definition. - */ -/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ -#define R(b,x) ((x) >> (b)) -/* 32-bit Rotate-right (used in SHA-256): */ -#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) -/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ -#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) - -/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ -#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) -#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) - -/* Four of six logical functions used in SHA-256: */ -#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) -#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) -#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) -#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) - -/* Four of six logical functions used in SHA-384 and SHA-512: */ -#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) -#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) -#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) -#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) - -/*** INTERNAL FUNCTION PROTOTYPES *************************************/ -/* NOTE: These should not be accessed directly from outside this - * library -- they are intended for private internal visibility/use - * only. - */ -static void SHA512_Last(SHA512_CTX*); -static void SHA256_Transform(SHA256_CTX*, const uint32_t*); -static void SHA512_Transform(SHA512_CTX*, const uint64_t*); - - -/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ -/* Hash constant words K for SHA-256: */ -static const uint32_t K256[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, - 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, - 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, - 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, - 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, - 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, - 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, - 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, - 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, - 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, - 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, - 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, - 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL -}; - -/* Initial hash value H for SHA-256: */ -static const uint32_t sha256_initial_hash_value[8] = { - 0x6a09e667UL, - 0xbb67ae85UL, - 0x3c6ef372UL, - 0xa54ff53aUL, - 0x510e527fUL, - 0x9b05688cUL, - 0x1f83d9abUL, - 0x5be0cd19UL -}; - -/* Hash constant words K for SHA-384 and SHA-512: */ -static const uint64_t K512[80] = { - 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, - 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, - 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, - 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, - 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, - 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, - 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, - 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, - 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, - 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, - 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, - 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, - 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, - 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, - 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, - 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, - 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, - 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, - 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, - 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, - 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, - 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, - 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, - 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, - 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, - 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, - 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, - 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, - 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, - 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, - 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, - 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, - 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, - 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, - 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, - 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, - 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, - 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, - 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, - 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL -}; - -/* Initial hash value H for SHA-384 */ -static const uint64_t sha384_initial_hash_value[8] = { - 0xcbbb9d5dc1059ed8ULL, - 0x629a292a367cd507ULL, - 0x9159015a3070dd17ULL, - 0x152fecd8f70e5939ULL, - 0x67332667ffc00b31ULL, - 0x8eb44a8768581511ULL, - 0xdb0c2e0d64f98fa7ULL, - 0x47b5481dbefa4fa4ULL -}; - -/* Initial hash value H for SHA-512 */ -static const uint64_t sha512_initial_hash_value[8] = { - 0x6a09e667f3bcc908ULL, - 0xbb67ae8584caa73bULL, - 0x3c6ef372fe94f82bULL, - 0xa54ff53a5f1d36f1ULL, - 0x510e527fade682d1ULL, - 0x9b05688c2b3e6c1fULL, - 0x1f83d9abfb41bd6bULL, - 0x5be0cd19137e2179ULL -}; - -/* - * Constant used by SHA256/384/512_End() functions for converting the - * digest to a readable hexadecimal character string: - */ - -//static const char *sha2_hex_digits = "0123456789abcdef"; // PJ - - -/*** SHA-256: *********************************************************/ -static void SHA256_Init(SHA256_CTX* context) { - if (context == (SHA256_CTX*)0) { - return; - } - MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); - MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH); - context->bitcount = 0; -} - -#ifdef SHA2_UNROLL_TRANSFORM - -/* Unrolled SHA-256 round macros: */ - -#if BYTE_ORDER == LITTLE_ENDIAN - -#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ - REVERSE32(*data++, W256[j]); \ - T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ - K256[j] + W256[j]; \ - (d) += T1; \ - (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ - j++ - - -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - -#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ - T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ - K256[j] + (W256[j] = *data++); \ - (d) += T1; \ - (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ - j++ - -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -#define ROUND256(a,b,c,d,e,f,g,h) \ - s0 = W256[(j+1)&0x0f]; \ - s0 = sigma0_256(s0); \ - s1 = W256[(j+14)&0x0f]; \ - s1 = sigma1_256(s1); \ - T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ - (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ - (d) += T1; \ - (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ - j++ - -void SHA256_Transform(SHA256_CTX* context, const uint32_t* data) { - uint32_t a, b, c, d, e, f, g, h, s0, s1; - uint32_t T1, *W256; - int j; - - W256 = (uint32_t*)context->buffer; - - /* Initialize registers with the prev. intermediate value */ - a = context->state[0]; - b = context->state[1]; - c = context->state[2]; - d = context->state[3]; - e = context->state[4]; - f = context->state[5]; - g = context->state[6]; - h = context->state[7]; - - j = 0; - do { - /* Rounds 0 to 15 (unrolled): */ - ROUND256_0_TO_15(a,b,c,d,e,f,g,h); - ROUND256_0_TO_15(h,a,b,c,d,e,f,g); - ROUND256_0_TO_15(g,h,a,b,c,d,e,f); - ROUND256_0_TO_15(f,g,h,a,b,c,d,e); - ROUND256_0_TO_15(e,f,g,h,a,b,c,d); - ROUND256_0_TO_15(d,e,f,g,h,a,b,c); - ROUND256_0_TO_15(c,d,e,f,g,h,a,b); - ROUND256_0_TO_15(b,c,d,e,f,g,h,a); - } while (j < 16); - - /* Now for the remaining rounds to 64: */ - do { - ROUND256(a,b,c,d,e,f,g,h); - ROUND256(h,a,b,c,d,e,f,g); - ROUND256(g,h,a,b,c,d,e,f); - ROUND256(f,g,h,a,b,c,d,e); - ROUND256(e,f,g,h,a,b,c,d); - ROUND256(d,e,f,g,h,a,b,c); - ROUND256(c,d,e,f,g,h,a,b); - ROUND256(b,c,d,e,f,g,h,a); - } while (j < 64); - - /* Compute the current intermediate hash value */ - context->state[0] += a; - context->state[1] += b; - context->state[2] += c; - context->state[3] += d; - context->state[4] += e; - context->state[5] += f; - context->state[6] += g; - context->state[7] += h; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = 0; -} - -#else /* SHA2_UNROLL_TRANSFORM */ - -static void SHA256_Transform(SHA256_CTX* context, const uint32_t* data) { - uint32_t a, b, c, d, e, f, g, h, s0, s1; - uint32_t T1, T2, *W256; - int j; - -#if ARM_COMPLIANT - W256 = (uint32_t*)((void *)context->buffer); -#else - W256 = (uint32_t*)context->buffer; -#endif - - - /* Initialize registers with the prev. intermediate value */ - a = context->state[0]; - b = context->state[1]; - c = context->state[2]; - d = context->state[3]; - e = context->state[4]; - f = context->state[5]; - g = context->state[6]; - h = context->state[7]; - - j = 0; - do { -#if BYTE_ORDER == LITTLE_ENDIAN - /* Copy data while converting to host byte order */ - REVERSE32(*data++,W256[j]); - /* Apply the SHA-256 compression function to update a..h */ - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - /* Apply the SHA-256 compression function to update a..h with copy */ - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - T2 = Sigma0_256(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 16); - - do { - /* Part of the message block expansion: */ - s0 = W256[(j+1)&0x0f]; - s0 = sigma0_256(s0); - s1 = W256[(j+14)&0x0f]; - s1 = sigma1_256(s1); - - /* Apply the SHA-256 compression function to update a..h */ - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + - (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); - T2 = Sigma0_256(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 64); - - /* Compute the current intermediate hash value */ - context->state[0] += a; - context->state[1] += b; - context->state[2] += c; - context->state[3] += d; - context->state[4] += e; - context->state[5] += f; - context->state[6] += g; - context->state[7] += h; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = T2 = 0; -} - -#endif /* SHA2_UNROLL_TRANSFORM */ - -static void SHA256_Update(SHA256_CTX* context, const uint8_t *data, size_t len) { - unsigned int freespace, usedspace; - - if (len == 0) { - /* Calling with no data is valid - we do nothing */ - return; - } - - /* Sanity check: */ - assert(context != (SHA256_CTX*)0 && data != (uint8_t*)0); - - usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; - if (usedspace > 0) { - /* Calculate how much free space is available in the buffer */ - freespace = SHA256_BLOCK_LENGTH - usedspace; - - if (len >= freespace) { - /* Fill the buffer completely and process it */ - MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); - context->bitcount += freespace << 3; - len -= freespace; - data += freespace; -#if ARM_COMPLIANT - SHA256_Transform(context, (uint32_t*)((void *)context->buffer)); -#else - SHA256_Transform(context, (uint32_t*)context->buffer); -#endif - - } else { - /* The buffer is not yet full */ - MEMCPY_BCOPY(&context->buffer[usedspace], data, len); - context->bitcount += len << 3; - /* Clean up: */ - usedspace = freespace = 0; - return; - } - } - while (len >= SHA256_BLOCK_LENGTH) { - /* Process as many complete blocks as we can */ -#if ARM_COMPLIANT - SHA256_Transform(context, (const uint32_t*)(const void *)(data)); -#else - SHA256_Transform(context, (const uint32_t*)data); -#endif - - context->bitcount += SHA256_BLOCK_LENGTH << 3; - len -= SHA256_BLOCK_LENGTH; - data += SHA256_BLOCK_LENGTH; - } - if (len > 0) { - /* There's left-overs, so save 'em */ - MEMCPY_BCOPY(context->buffer, data, len); - context->bitcount += len << 3; - } - /* Clean up: */ - usedspace = freespace = 0; -} - -static void SHA256_Final(uint8_t digest[], SHA256_CTX* context) { -#if ARM_COMPLIANT - uint32_t *d ; -#else - uint32_t *d = (uint32_t*)digest; - -#endif - unsigned int usedspace; - - /* Sanity check: */ - assert(context != (SHA256_CTX*)0); -#if ARM_COMPLIANT - d = malloc(sizeof(uint32_t)*8); /* why 8 ? see below for loop */ - assert(d); -#endif - - /* If no digest buffer is passed, we don't bother doing this: */ - if (digest != (uint8_t*)0) { - usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; -#if BYTE_ORDER == LITTLE_ENDIAN - /* Convert FROM host byte order */ - REVERSE64(context->bitcount,context->bitcount); -#endif - if (usedspace > 0) { - /* Begin padding with a 1 bit: */ - context->buffer[usedspace++] = 0x80; - - if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { - /* Set-up for the last transform: */ - MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace); - } else { - if (usedspace < SHA256_BLOCK_LENGTH) { - MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); - } - /* Do second-to-last transform: */ -#if ARM_COMPLIANT - SHA256_Transform(context, (uint32_t*)(void *)(context->buffer)); -#else - SHA256_Transform(context, (uint32_t*)context->buffer); -#endif - - - /* And set-up for the last transform: */ - MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); - } - } else { - /* Set-up for the last transform: */ - MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); - - /* Begin padding with a 1 bit: */ - *context->buffer = 0x80; - } - /* Set the bit count: */ - //*(uint64_t*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; // aliasing violation warning - context->buffer64[SHA256_SHORT_BLOCK_LENGTH / sizeof(uint64_t)] = context->bitcount; - - /* Final transform: */ -#if ARM_COMPLIANT - SHA256_Transform(context, (uint32_t*)((void *)(context->buffer))); -#else - SHA256_Transform(context, (uint32_t*)context->buffer); - -#endif - -#if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < 8; j++) { - REVERSE32(context->state[j],context->state[j]); - *d++ = context->state[j]; - } - } -#else - MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH); -#endif - } - -#if ARM_COMPLIANT - memcpy(digest,d,SHA256_DIGEST_LENGTH); - free(d); -#endif - - /* Clean up state data: */ - MEMSET_BZERO(context, sizeof(*context)); - usedspace = 0; -} - -/* -static char *SHA256_End(SHA256_CTX* context, char buffer[]) { - uint8_t digest[SHA256_DIGEST_LENGTH], *d = digest; - int i; - - / * Sanity check: * / - assert(context != (SHA256_CTX*)0); - - if (buffer != (char*)0) { - SHA256_Final(digest, context); - - for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { - *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; - *buffer++ = sha2_hex_digits[*d & 0x0f]; - d++; - } - *buffer = (char)0; - } else { - MEMSET_BZERO(context, sizeof(context)); - } - MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH); - return buffer; -} - -static char* SHA256_Data(const uint8_t* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) { - SHA256_CTX context; - - SHA256_Init(&context); - SHA256_Update(&context, data, len); - return SHA256_End(&context, digest); -} -*/ - - -/*** SHA-512: *********************************************************/ -static void SHA512_Init(SHA512_CTX* context) { - if (context == (SHA512_CTX*)0) { - return; - } - MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH); - MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH); - context->bitcount[0] = context->bitcount[1] = 0; -} - -#ifdef SHA2_UNROLL_TRANSFORM - -/* Unrolled SHA-512 round macros: */ -#if BYTE_ORDER == LITTLE_ENDIAN - -#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ - REVERSE64(*data++, W512[j]); \ - T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ - K512[j] + W512[j]; \ - (d) += T1, \ - (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \ - j++ - - -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - -#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ - T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ - K512[j] + (W512[j] = *data++); \ - (d) += T1; \ - (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ - j++ - -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -#define ROUND512(a,b,c,d,e,f,g,h) \ - s0 = W512[(j+1)&0x0f]; \ - s0 = sigma0_512(s0); \ - s1 = W512[(j+14)&0x0f]; \ - s1 = sigma1_512(s1); \ - T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ - (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ - (d) += T1; \ - (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ - j++ - -static void SHA512_Transform(SHA512_CTX* context, const uint64_t* data) { - uint64_t a, b, c, d, e, f, g, h, s0, s1; - uint64_t T1, *W512 = (uint64_t*)context->buffer; - int j; - - /* Initialize registers with the prev. intermediate value */ - a = context->state[0]; - b = context->state[1]; - c = context->state[2]; - d = context->state[3]; - e = context->state[4]; - f = context->state[5]; - g = context->state[6]; - h = context->state[7]; - - j = 0; - do { - ROUND512_0_TO_15(a,b,c,d,e,f,g,h); - ROUND512_0_TO_15(h,a,b,c,d,e,f,g); - ROUND512_0_TO_15(g,h,a,b,c,d,e,f); - ROUND512_0_TO_15(f,g,h,a,b,c,d,e); - ROUND512_0_TO_15(e,f,g,h,a,b,c,d); - ROUND512_0_TO_15(d,e,f,g,h,a,b,c); - ROUND512_0_TO_15(c,d,e,f,g,h,a,b); - ROUND512_0_TO_15(b,c,d,e,f,g,h,a); - } while (j < 16); - - /* Now for the remaining rounds up to 79: */ - do { - ROUND512(a,b,c,d,e,f,g,h); - ROUND512(h,a,b,c,d,e,f,g); - ROUND512(g,h,a,b,c,d,e,f); - ROUND512(f,g,h,a,b,c,d,e); - ROUND512(e,f,g,h,a,b,c,d); - ROUND512(d,e,f,g,h,a,b,c); - ROUND512(c,d,e,f,g,h,a,b); - ROUND512(b,c,d,e,f,g,h,a); - } while (j < 80); - - /* Compute the current intermediate hash value */ - context->state[0] += a; - context->state[1] += b; - context->state[2] += c; - context->state[3] += d; - context->state[4] += e; - context->state[5] += f; - context->state[6] += g; - context->state[7] += h; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = 0; -} - -#else /* SHA2_UNROLL_TRANSFORM */ - -static void SHA512_Transform(SHA512_CTX* context, const uint64_t* data) { - uint64_t a, b, c, d, e, f, g, h, s0, s1; - uint64_t T1, T2, *W512 = (uint64_t*)((void *)context->buffer); - int j; - - /* Initialize registers with the prev. intermediate value */ - a = context->state[0]; - b = context->state[1]; - c = context->state[2]; - d = context->state[3]; - e = context->state[4]; - f = context->state[5]; - g = context->state[6]; - h = context->state[7]; - - j = 0; - do { -#if BYTE_ORDER == LITTLE_ENDIAN - /* Convert TO host byte order */ - REVERSE64(*data++, W512[j]); - /* Apply the SHA-512 compression function to update a..h */ - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - /* Apply the SHA-512 compression function to update a..h with copy */ - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - T2 = Sigma0_512(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 16); - - do { - /* Part of the message block expansion: */ - s0 = W512[(j+1)&0x0f]; - s0 = sigma0_512(s0); - s1 = W512[(j+14)&0x0f]; - s1 = sigma1_512(s1); - - /* Apply the SHA-512 compression function to update a..h */ - T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + - (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); - T2 = Sigma0_512(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 80); - - /* Compute the current intermediate hash value */ - context->state[0] += a; - context->state[1] += b; - context->state[2] += c; - context->state[3] += d; - context->state[4] += e; - context->state[5] += f; - context->state[6] += g; - context->state[7] += h; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = T2 = 0; -} - -#endif /* SHA2_UNROLL_TRANSFORM */ - -static void SHA512_Update(SHA512_CTX* context, const uint8_t *data, size_t len) { - unsigned int freespace, usedspace; - - if (len == 0) { - /* Calling with no data is valid - we do nothing */ - return; - } - - /* Sanity check: */ - assert(context != (SHA512_CTX*)0 && data != (uint8_t*)0); - - usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; - if (usedspace > 0) { - /* Calculate how much free space is available in the buffer */ - freespace = SHA512_BLOCK_LENGTH - usedspace; - - if (len >= freespace) { - /* Fill the buffer completely and process it */ - MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); - ADDINC128(context->bitcount, freespace << 3); - len -= freespace; - data += freespace; -#if ARM_COMPLIANT - SHA512_Transform(context, (uint64_t*)((void *)context->buffer)); -#else - SHA512_Transform(context, (uint64_t*)context->buffer); -#endif - } else { - /* The buffer is not yet full */ - MEMCPY_BCOPY(&context->buffer[usedspace], data, len); - ADDINC128(context->bitcount, len << 3); - /* Clean up: */ - usedspace = freespace = 0; - return; - } - } - while (len >= SHA512_BLOCK_LENGTH) { - /* Process as many complete blocks as we can */ -#if ARM_COMPLIANT - SHA512_Transform(context, (uint64_t*)((void *)data)); -#else - SHA512_Transform(context, (uint64_t*)data); -#endif - ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); - len -= SHA512_BLOCK_LENGTH; - data += SHA512_BLOCK_LENGTH; - } - if (len > 0) { - /* There's left-overs, so save 'em */ - MEMCPY_BCOPY(context->buffer, data, len); - ADDINC128(context->bitcount, len << 3); - } - /* Clean up: */ - usedspace = freespace = 0; -} - -static void SHA512_Last(SHA512_CTX* context) { - unsigned int usedspace; - - usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; -#if BYTE_ORDER == LITTLE_ENDIAN - /* Convert FROM host byte order */ - REVERSE64(context->bitcount[0],context->bitcount[0]); - REVERSE64(context->bitcount[1],context->bitcount[1]); -#endif - if (usedspace > 0) { - /* Begin padding with a 1 bit: */ - context->buffer[usedspace++] = 0x80; - - if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { - /* Set-up for the last transform: */ - MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace); - } else { - if (usedspace < SHA512_BLOCK_LENGTH) { - MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace); - } - /* Do second-to-last transform: */ -#if ARM_COMPLIANT - SHA512_Transform(context, (uint64_t*)((void *)context->buffer)); -#else - SHA512_Transform(context, (uint64_t*)context->buffer); -#endif - - - /* And set-up for the last transform: */ - MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2); - } - } else { - /* Prepare for final transform: */ - MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH); - - /* Begin padding with a 1 bit: */ - *context->buffer = 0x80; - } - /* Store the length of input data (in bits): */ - //*(uint64_t*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; // aliasing violation warning - //*(uint64_t*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0]; - context->buffer64[SHA512_SHORT_BLOCK_LENGTH / sizeof(uint64_t)] = context->bitcount[1]; - context->buffer64[SHA512_SHORT_BLOCK_LENGTH / sizeof(uint64_t) + 1] = context->bitcount[0]; - - /* Final transform: */ -#if ARM_COMPLIANT - SHA512_Transform(context, (uint64_t*)((void *)context->buffer)); -#else - SHA512_Transform(context, (uint64_t*)context->buffer); -#endif - -} - -static void SHA512_Final(uint8_t digest[], SHA512_CTX* context) { -#if ARM_COMPLIANT - uint64_t *d ; -#else - uint64_t *d = (uint64_t*)digest; -#endif - - /* Sanity check: */ - assert(context != (SHA512_CTX*)0); -#if ARM_COMPLIANT - d = malloc(sizeof(uint64_t)*8); /* why 8 ? see below for loop */ - assert(d); -#endif - - /* If no digest buffer is passed, we don't bother doing this: */ - if (digest != (uint8_t*)0) { - SHA512_Last(context); - - /* Save the hash data for output: */ -#if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < 8; j++) { - REVERSE64(context->state[j],context->state[j]); - *d++ = context->state[j]; - } - } -#else - MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH); -#endif - } -#if ARM_COMPLIANT - memcpy(digest,d,SHA512_DIGEST_LENGTH); - free(d); -#endif - - /* Zero out state data */ - MEMSET_BZERO(context, sizeof(*context)); -} - -/* -static char *SHA512_End(SHA512_CTX* context, char buffer[]) { - uint8_t digest[SHA512_DIGEST_LENGTH], *d = digest; - int i; - - / * Sanity check: * / - assert(context != (SHA512_CTX*)0); - - if (buffer != (char*)0) { - SHA512_Final(digest, context); - - for (i = 0; i < SHA512_DIGEST_LENGTH; i++) { - *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; - *buffer++ = sha2_hex_digits[*d & 0x0f]; - d++; - } - *buffer = (char)0; - } else { - MEMSET_BZERO(context, sizeof(context)); - } - MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH); - return buffer; -} - -static char* SHA512_Data(const uint8_t* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) { - SHA512_CTX context; - - SHA512_Init(&context); - SHA512_Update(&context, data, len); - return SHA512_End(&context, digest); -} -*/ - -/*** SHA-384: *********************************************************/ -static void SHA384_Init(SHA384_CTX* context) { - if (context == (SHA384_CTX*)0) { - return; - } - MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH); - MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH); - context->bitcount[0] = context->bitcount[1] = 0; -} - -static void SHA384_Update(SHA384_CTX* context, const uint8_t* data, size_t len) { - SHA512_Update((SHA512_CTX*)context, data, len); -} - -static void SHA384_Final(uint8_t digest[], SHA384_CTX* context) { -#if ARM_COMPLIANT - uint64_t *d; -#else - uint64_t *d = (uint64_t*)digest; -#endif - - - - /* Sanity check: */ - assert(context != (SHA384_CTX*)0); -#if ARM_COMPLIANT - d = malloc(sizeof(uint64_t)*6); /* why 6 ? see below for loop */ - assert(d); -#endif - - /* If no digest buffer is passed, we don't bother doing this: */ - if (digest != (uint8_t*)0) { - SHA512_Last((SHA512_CTX*)context); - - /* Save the hash data for output: */ -#if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < 6; j++) { - REVERSE64(context->state[j],context->state[j]); - *d++ = context->state[j]; - } - } -#else - MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH); -#endif - } -#if ARM_COMPLIANT - memcpy(digest,d,SHA384_DIGEST_LENGTH); - free(d); -#endif - /* Zero out state data */ - MEMSET_BZERO(context, sizeof(*context)); -} - -/* -static char *SHA384_End(SHA384_CTX* context, char buffer[]) { - uint8_t digest[SHA384_DIGEST_LENGTH], *d = digest; - int i; - - / * Sanity check: * / - assert(context != (SHA384_CTX*)0); - - if (buffer != (char*)0) { - SHA384_Final(digest, context); - - for (i = 0; i < SHA384_DIGEST_LENGTH; i++) { - *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; - *buffer++ = sha2_hex_digits[*d & 0x0f]; - d++; - } - *buffer = (char)0; - } else { - MEMSET_BZERO(context, sizeof(context)); - } - MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH); - return buffer; -} - -static char* SHA384_Data(const uint8_t* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) { - SHA384_CTX context; - - SHA384_Init(&context); - SHA384_Update(&context, data, len); - return SHA384_End(&context, digest); -} -*/ - -/* end of sha2.c */ - -void sha256_init (sha256_state *state) -{ - SHA256_Init(state); -} - -void sha384_init (sha384_state *state) -{ - SHA384_Init(state); -} - -void sha512_init (sha512_state *state) -{ - SHA512_Init(state); -} - - -void sha256_add (sha256_state *state, const void *data, size_t size) -{ - SHA256_Update(state, (const uint8_t *)data, size); -} - -void sha384_add (sha384_state *state, const void *data, size_t size) -{ - SHA384_Update(state, (const uint8_t *)data, size); -} - -void sha512_add (sha512_state *state, const void *data, size_t size) -{ - SHA512_Update(state, (const uint8_t *)data, size); -} - - -void sha256_put (sha256_state *state, uint8_t digest[SHA256_DIGEST_LENGTH]) -{ - SHA256_Final(digest, state); -} - -void sha384_put (sha384_state *state, uint8_t digest[SHA384_DIGEST_LENGTH]) -{ - SHA384_Final(digest, state); -} - -void sha512_put (sha384_state *state, uint8_t digest[SHA512_DIGEST_LENGTH]) -{ - SHA512_Final(digest, state); -} - - -void sha256 (const void *data, size_t size, uint8_t digest[SHA256_DIGEST_LENGTH]) -{ - sha256_state state; - SHA256_Init(&state); - SHA256_Update(&state, (const uint8_t *)data, size); - SHA256_Final(digest, &state); -} - -void sha384 (const void *data, size_t size, uint8_t digest[SHA384_DIGEST_LENGTH]) -{ - sha384_state state; - SHA384_Init(&state); - SHA384_Update(&state, (const uint8_t *)data, size); - SHA384_Final(digest, &state); -} - -void sha512 (const void *data, size_t size, uint8_t digest[SHA512_DIGEST_LENGTH]) -{ - sha512_state state; - SHA512_Init(&state); - SHA512_Update(&state, (const uint8_t *)data, size); - SHA512_Final(digest, &state); -} - -static sha256_state sha256state; -static sha384_state sha384state; -static sha512_state sha512state; - - -void sha256init (void) -{ - SHA256_Init(&sha256state); -} - -void sha384init (void) -{ - SHA384_Init(&sha384state); -} - -void sha512init (void) -{ - SHA512_Init(&sha512state); -} - - -void sha256add (const void *data, size_t size) -{ - SHA256_Update(&sha256state, (const uint8_t *)data, size); -} - -void sha384add (const void *data, size_t size) -{ - SHA384_Update(&sha384state, (const uint8_t *)data, size); -} - -void sha512add (const void *data, size_t size) -{ - SHA512_Update(&sha512state, (const uint8_t *)data, size); -} - - -void sha256put (uint8_t digest[SHA256_DIGEST_LENGTH]) -{ - SHA256_Final(digest, &sha256state); -} - -void sha384put (uint8_t digest[SHA384_DIGEST_LENGTH]) -{ - SHA384_Final(digest, &sha384state); -} - -void sha512put (uint8_t digest[SHA512_DIGEST_LENGTH]) -{ - SHA512_Final(digest, &sha512state); -} diff --git a/Build/source/texk/web2c/luatexdir/luapplib/util/utilsha.h b/Build/source/texk/web2c/luatexdir/luapplib/util/utilsha.h deleted file mode 100644 index 53f35458181..00000000000 --- a/Build/source/texk/web2c/luatexdir/luapplib/util/utilsha.h +++ /dev/null @@ -1,134 +0,0 @@ -/* sha2 implementation by Aaron D. Gifford (http://www.aarongifford.com) */ - -#ifndef UTIL_SHA_H -#define UTIL_SHA_H - -#include <stddef.h> -#include <stdint.h> -#include "utildecl.h" - -/* begin of sha2.h */ - -/* - * FILE: sha2.h - * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ - * - * Copyright (c) 2000-2001, Aaron D. Gifford - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ - */ - -/*** SHA-256/384/512 Various Length Definitions ***********************/ - -#define SHA256_BLOCK_LENGTH 64 -#define SHA256_DIGEST_LENGTH 32 -#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) -#define SHA384_BLOCK_LENGTH 128 -#define SHA384_DIGEST_LENGTH 48 -#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) -#define SHA512_BLOCK_LENGTH 128 -#define SHA512_DIGEST_LENGTH 64 -#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) - -typedef struct _SHA256_CTX { - uint32_t state[8]; - uint64_t bitcount; - union { - uint8_t buffer[SHA256_BLOCK_LENGTH]; - uint64_t buffer64[SHA256_BLOCK_LENGTH / sizeof(uint64_t)]; // to avoid warnings about violating aliasing rules - }; -} SHA256_CTX; - -typedef struct _SHA512_CTX { - uint64_t state[8]; - uint64_t bitcount[2]; - union { - uint8_t buffer[SHA512_BLOCK_LENGTH]; - uint64_t buffer64[SHA512_BLOCK_LENGTH / sizeof(uint64_t)]; - }; -} SHA512_CTX; - -typedef SHA512_CTX SHA384_CTX; - -/*** SHA-256/384/512 Function Prototypes ******************************/ - -/* -void SHA256_Init(SHA256_CTX *); -void SHA256_Update(SHA256_CTX*, const u_int8_t*, size_t); -void SHA256_Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*); -char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); -char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); - -void SHA384_Init(SHA384_CTX*); -void SHA384_Update(SHA384_CTX*, const u_int8_t*, size_t); -void SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*); -char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]); -char* SHA384_Data(const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]); - -void SHA512_Init(SHA512_CTX*); -void SHA512_Update(SHA512_CTX*, const u_int8_t*, size_t); -void SHA512_Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); -char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); -char* SHA512_Data(const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]); -*/ - -/* end of sha2.h */ - -#define sha256_state SHA256_CTX -#define sha384_state SHA384_CTX -#define sha512_state SHA512_CTX - -UTILAPI void sha256_init (sha256_state *state); -UTILAPI void sha384_init (sha384_state *state); -UTILAPI void sha512_init (sha512_state *state); - -UTILAPI void sha256_add (sha256_state *state, const void *data, size_t size); -UTILAPI void sha384_add (sha384_state *state, const void *data, size_t size); -UTILAPI void sha512_add (sha512_state *state, const void *data, size_t size); - -UTILAPI void sha256_put (sha256_state *state, uint8_t digest[SHA256_DIGEST_LENGTH]); -UTILAPI void sha384_put (sha384_state *state, uint8_t digest[SHA384_DIGEST_LENGTH]); -UTILAPI void sha512_put (sha512_state *state, uint8_t digest[SHA512_DIGEST_LENGTH]); - -UTILAPI void sha256 (const void *data, size_t size, uint8_t digest[SHA256_DIGEST_LENGTH]); -UTILAPI void sha384 (const void *data, size_t size, uint8_t digest[SHA384_DIGEST_LENGTH]); -UTILAPI void sha512 (const void *data, size_t size, uint8_t digest[SHA512_DIGEST_LENGTH]); - -UTILAPI void sha256init (void); -UTILAPI void sha384init (void); -UTILAPI void sha512init (void); - -UTILAPI void sha256add (const void *data, size_t size); -UTILAPI void sha384add (const void *data, size_t size); -UTILAPI void sha512add (const void *data, size_t size); - -UTILAPI void sha256put (uint8_t digest[SHA256_DIGEST_LENGTH]); -UTILAPI void sha384put (uint8_t digest[SHA384_DIGEST_LENGTH]); -UTILAPI void sha512put (uint8_t digest[SHA512_DIGEST_LENGTH]); - -#endif
\ No newline at end of file |