Add FreeInkBook EPUB engine migration guide

Document migration plan from CrossPoint's lib/Epub to FreeInkBook, a memory-efficient clean-room EPUB engine. Covers advantages (O(paragraph+page) memory via SAX parsing, arena allocation, host-testable, full UAX#14 typography, runtime TTF/OTF support), 9-step migration strategy, ESP32-C3 constraints, and integration approach preserving existing UI layer while replacing parsing/layout stack.
This commit is contained in:
Justin Mitchell
2026-07-08 00:22:21 -04:00
parent 5776911af0
commit 0848649ce2
49 changed files with 1065 additions and 15633 deletions
+15
View File
@@ -154,6 +154,21 @@ uint32_t EpdFont::applyLigatures(uint32_t cp, const char*& text) const {
return cp;
}
bool EpdFont::hasGlyph(const uint32_t cp) const {
const int count = data->intervalCount;
if (count > 0) {
const EpdUnicodeInterval* intervals = data->intervals;
const auto it =
std::upper_bound(intervals, intervals + count, cp,
[](uint32_t value, const EpdUnicodeInterval& interval) { return value < interval.first; });
if (it != intervals && cp <= (it - 1)->last) return true;
}
if (data->glyphMissHandler) {
return data->glyphMissHandler(data->glyphMissCtx, cp) != nullptr;
}
return false;
}
const EpdGlyph* EpdFont::getGlyph(const uint32_t cp) const {
const int count = data->intervalCount;
if (count == 0 && !data->glyphMissHandler) return nullptr;
+6
View File
@@ -12,6 +12,12 @@ class EpdFont {
const EpdGlyph* getGlyph(uint32_t cp) const;
/// True when the font actually provides `cp` (interval table or on-demand
/// SD load) — unlike getGlyph(), never satisfied by the replacement glyph.
/// Used by layout shaping to decide whether a substitution (ligature,
/// Arabic presentation form) can really be drawn.
bool hasGlyph(uint32_t cp) const;
/// Returns the kerning adjustment (4.4 fixed-point in pixels) between two codepoints.
/// Returns 0 if no kerning data exists for the pair.
int8_t getKerning(uint32_t leftCp, uint32_t rightCp) const;
+8
View File
@@ -28,10 +28,18 @@ const EpdGlyph* EpdFontFamily::getGlyph(const uint32_t cp, const Style style) co
return getFont(style)->getGlyph(cp);
}
bool EpdFontFamily::hasGlyph(const uint32_t cp, const Style style) const {
return getFont(style)->hasGlyph(cp);
}
int8_t EpdFontFamily::getKerning(const uint32_t leftCp, const uint32_t rightCp, const Style style) const {
return getFont(style)->getKerning(leftCp, rightCp);
}
uint32_t EpdFontFamily::getLigature(const uint32_t leftCp, const uint32_t rightCp, const Style style) const {
return getFont(style)->getLigature(leftCp, rightCp);
}
uint32_t EpdFontFamily::applyLigatures(const uint32_t cp, const char*& text, const Style style) const {
return getFont(style)->applyLigatures(cp, text);
}
+2
View File
@@ -26,7 +26,9 @@ class EpdFontFamily {
void getTextDimensions(const char* string, int* w, int* h, Style style = REGULAR) const;
const EpdFontData* getData(Style style = REGULAR) const;
const EpdGlyph* getGlyph(uint32_t cp, Style style = REGULAR) const;
bool hasGlyph(uint32_t cp, Style style = REGULAR) const;
int8_t getKerning(uint32_t leftCp, uint32_t rightCp, Style style = REGULAR) const;
uint32_t getLigature(uint32_t leftCp, uint32_t rightCp, Style style = REGULAR) const;
uint32_t applyLigatures(uint32_t cp, const char*& text, Style style = REGULAR) const;
static constexpr bool hasTextDecoration(const Style style) {
return (static_cast<uint8_t>(style) & TEXT_DECORATION_MASK) != 0;
@@ -6,7 +6,7 @@
#include <Logging.h>
#include <Utf8.h>
#include <XmlParserUtils.h>
#include <expat.h>
#include <epub/Expat.h> // FreeInkBook's vendored expat
#include <algorithm>
#include <iterator>
@@ -1,7 +1,7 @@
#pragma once
#include <HalStorage.h>
#include <expat.h>
#include <epub/Expat.h> // FreeInkBook's vendored expat
#include <climits>
#include <functional>
+1 -1
View File
@@ -3,7 +3,7 @@
#include <string>
#include "expat.h"
#include <epub/Expat.h> // FreeInkBook's vendored expat
class ContainerParser final : public Print {
enum ParserState {
+1 -1
View File
@@ -6,7 +6,7 @@
#include <vector>
#include "Epub.h"
#include "expat.h"
#include <epub/Expat.h> // FreeInkBook's vendored expat
class BookMetadataCache;
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#include <Print.h>
#include <expat.h>
#include <epub/Expat.h> // FreeInkBook's vendored expat
#include <string>
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#include <Print.h>
#include <expat.h>
#include <epub/Expat.h> // FreeInkBook's vendored expat
#include <string>
+1 -1
View File
@@ -4,7 +4,7 @@
#include <Print.h>
#include <Utf8.h>
#include <XmlParserUtils.h>
#include <expat.h>
#include <epub/Expat.h> // FreeInkBook's vendored expat
#include <algorithm>
#include <cmath>
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#include <Print.h>
#include <expat.h>
#include <epub/Expat.h> // FreeInkBook's vendored expat
#include <string>
#include <vector>
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#include <expat.h>
#include <epub/Expat.h> // FreeInkBook's vendored expat
// Safely tear down an expat parser: stop processing, clear callbacks, free, and null the pointer.
inline void destroyXmlParser(XML_Parser& parser) {
-17
View File
@@ -1,17 +0,0 @@
Makefile
.libs
*.lo
Debug
Debug-w
Release
Release-w
expat.ncb
expat.opt
expat.plg
Debug_static
Debug-w_static
Release_static
Release-w_static
expat_static.plg
expatw.plg
expatw_static.plg
-87
View File
@@ -1,87 +0,0 @@
#
# __ __ _
# ___\ \/ /_ __ __ _| |_
# / _ \\ /| '_ \ / _` | __|
# | __// \| |_) | (_| | |_
# \___/_/\_\ .__/ \__,_|\__|
# |_| XML parser
#
# Copyright (c) 2017-2024 Sebastian Pipping <sebastian@pipping.org>
# Copyright (c) 2017 Tomasz Kłoczko <kloczek@fedoraproject.org>
# Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
# Licensed under the MIT license:
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the
# following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
# USE OR OTHER DEALINGS IN THE SOFTWARE.
include_HEADERS = \
../expat_config.h \
expat.h \
expat_external.h
lib_LTLIBRARIES = libexpat.la
if WITH_TESTS
noinst_LTLIBRARIES = libtestpat.la
endif
libexpat_la_LDFLAGS = \
@AM_LDFLAGS@ \
@LIBM@ \
-no-undefined \
-version-info @LIBCURRENT@:@LIBREVISION@:@LIBAGE@
libexpat_la_SOURCES = \
xmlparse.c \
xmltok.c \
xmlrole.c
if WITH_TESTS
libtestpat_la_CPPFLAGS = -DXML_TESTING
libtestpat_la_SOURCES = $(libexpat_la_SOURCES)
endif
doc_DATA = \
../AUTHORS \
../Changes
install-data-hook:
cd "$(DESTDIR)$(docdir)" && $(am__mv) Changes changelog
uninstall-local:
$(RM) "$(DESTDIR)$(docdir)/changelog"
EXTRA_DIST = \
ascii.h \
asciitab.h \
expat_external.h \
expat.h \
iasciitab.h \
internal.h \
latin1tab.h \
libexpat.def.cmake \
nametab.h \
siphash.h \
utf8tab.h \
winconfig.h \
xmlrole.h \
xmltok.h \
xmltok_impl.c \
xmltok_impl.h \
xmltok_ns.c
-123
View File
@@ -1,123 +0,0 @@
/*
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 1999-2000 Thai Open Source Software Center Ltd
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2007 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define ASCII_A 0x41
#define ASCII_B 0x42
#define ASCII_C 0x43
#define ASCII_D 0x44
#define ASCII_E 0x45
#define ASCII_F 0x46
#define ASCII_G 0x47
#define ASCII_H 0x48
#define ASCII_I 0x49
#define ASCII_J 0x4A
#define ASCII_K 0x4B
#define ASCII_L 0x4C
#define ASCII_M 0x4D
#define ASCII_N 0x4E
#define ASCII_O 0x4F
#define ASCII_P 0x50
#define ASCII_Q 0x51
#define ASCII_R 0x52
#define ASCII_S 0x53
#define ASCII_T 0x54
#define ASCII_U 0x55
#define ASCII_V 0x56
#define ASCII_W 0x57
#define ASCII_X 0x58
#define ASCII_Y 0x59
#define ASCII_Z 0x5A
#define ASCII_a 0x61
#define ASCII_b 0x62
#define ASCII_c 0x63
#define ASCII_d 0x64
#define ASCII_e 0x65
#define ASCII_f 0x66
#define ASCII_g 0x67
#define ASCII_h 0x68
#define ASCII_i 0x69
#define ASCII_j 0x6A
#define ASCII_k 0x6B
#define ASCII_l 0x6C
#define ASCII_m 0x6D
#define ASCII_n 0x6E
#define ASCII_o 0x6F
#define ASCII_p 0x70
#define ASCII_q 0x71
#define ASCII_r 0x72
#define ASCII_s 0x73
#define ASCII_t 0x74
#define ASCII_u 0x75
#define ASCII_v 0x76
#define ASCII_w 0x77
#define ASCII_x 0x78
#define ASCII_y 0x79
#define ASCII_z 0x7A
#define ASCII_0 0x30
#define ASCII_1 0x31
#define ASCII_2 0x32
#define ASCII_3 0x33
#define ASCII_4 0x34
#define ASCII_5 0x35
#define ASCII_6 0x36
#define ASCII_7 0x37
#define ASCII_8 0x38
#define ASCII_9 0x39
#define ASCII_TAB 0x09
#define ASCII_SPACE 0x20
#define ASCII_EXCL 0x21
#define ASCII_QUOT 0x22
#define ASCII_AMP 0x26
#define ASCII_APOS 0x27
#define ASCII_MINUS 0x2D
#define ASCII_PERIOD 0x2E
#define ASCII_COLON 0x3A
#define ASCII_SEMI 0x3B
#define ASCII_LT 0x3C
#define ASCII_EQUALS 0x3D
#define ASCII_GT 0x3E
#define ASCII_LSQB 0x5B
#define ASCII_RSQB 0x5D
#define ASCII_UNDERSCORE 0x5F
#define ASCII_LPAREN 0x28
#define ASCII_RPAREN 0x29
#define ASCII_FF 0x0C
#define ASCII_SLASH 0x2F
#define ASCII_HASH 0x23
#define ASCII_PIPE 0x7C
#define ASCII_COMMA 0x2C
-66
View File
@@ -1,66 +0,0 @@
/*
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
-1031
View File
File diff suppressed because it is too large Load Diff
View File
-163
View File
@@ -1,163 +0,0 @@
/*
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2000-2004 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2016 Cristian Rodríguez <crrodriguez@opensuse.org>
Copyright (c) 2016-2019 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2018 Yury Gribov <tetra2005@gmail.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Expat_External_INCLUDED
#define Expat_External_INCLUDED 1
/* External API definitions */
/* Expat tries very hard to make the API boundary very specifically
defined. There are two macros defined to control this boundary;
each of these can be defined before including this header to
achieve some different behavior, but doing so it not recommended or
tested frequently.
XMLCALL - The calling convention to use for all calls across the
"library boundary." This will default to cdecl, and
try really hard to tell the compiler that's what we
want.
XMLIMPORT - Whatever magic is needed to note that a function is
to be imported from a dynamically loaded library
(.dll, .so, or .sl, depending on your platform).
The XMLCALL macro was added in Expat 1.95.7. The only one which is
expected to be directly useful in client code is XMLCALL.
Note that on at least some Unix versions, the Expat library must be
compiled with the cdecl calling convention as the default since
system headers may assume the cdecl convention.
*/
#ifndef XMLCALL
#if defined(_MSC_VER)
#define XMLCALL __cdecl
#elif defined(__GNUC__) && defined(__i386) && !defined(__INTEL_COMPILER)
#define XMLCALL __attribute__((cdecl))
#else
/* For any platform which uses this definition and supports more than
one calling convention, we need to extend this definition to
declare the convention used on that platform, if it's possible to
do so.
If this is the case for your platform, please file a bug report
with information on how to identify your platform via the C
pre-processor and how to specify the same calling convention as the
platform's malloc() implementation.
*/
#define XMLCALL
#endif
#endif /* not defined XMLCALL */
#if !defined(XML_STATIC) && !defined(XMLIMPORT)
#ifndef XML_BUILDING_EXPAT
/* using Expat from an application */
#if defined(_MSC_VER) && !defined(__BEOS__) && !defined(__CYGWIN__)
#define XMLIMPORT __declspec(dllimport)
#endif
#endif
#endif /* not defined XML_STATIC */
#ifndef XML_ENABLE_VISIBILITY
#define XML_ENABLE_VISIBILITY 0
#endif
#if !defined(XMLIMPORT) && XML_ENABLE_VISIBILITY
#define XMLIMPORT __attribute__((visibility("default")))
#endif
/* If we didn't define it above, define it away: */
#ifndef XMLIMPORT
#define XMLIMPORT
#endif
#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
#define XML_ATTR_MALLOC __attribute__((__malloc__))
#else
#define XML_ATTR_MALLOC
#endif
#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
#define XML_ATTR_ALLOC_SIZE(x) __attribute__((__alloc_size__(x)))
#else
#define XML_ATTR_ALLOC_SIZE(x)
#endif
#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
#ifdef __cplusplus
extern "C" {
#endif
#ifdef XML_UNICODE_WCHAR_T
#ifndef XML_UNICODE
#define XML_UNICODE
#endif
#if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2)
#error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc"
#endif
#endif
#ifdef XML_UNICODE /* Information is UTF-16 encoded. */
#ifdef XML_UNICODE_WCHAR_T
typedef wchar_t XML_Char;
typedef wchar_t XML_LChar;
#else
typedef unsigned short XML_Char;
typedef char XML_LChar;
#endif /* XML_UNICODE_WCHAR_T */
#else /* Information is UTF-8 encoded. */
typedef char XML_Char;
typedef char XML_LChar;
#endif /* XML_UNICODE */
#ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */
typedef long long XML_Index;
typedef unsigned long long XML_Size;
#else
typedef long XML_Index;
typedef unsigned long XML_Size;
#endif /* XML_LARGE_SIZE */
#ifdef __cplusplus
}
#endif
#endif /* not Expat_External_INCLUDED */
-67
View File
@@ -1,67 +0,0 @@
/*
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
-187
View File
@@ -1,187 +0,0 @@
/* internal.h
Internal definitions used by Expat. This is not needed to compile
client code.
The following calling convention macros are defined for frequently
called functions:
FASTCALL - Used for those internal functions that have a simple
body and a low number of arguments and local variables.
PTRCALL - Used for functions called though function pointers.
PTRFASTCALL - Like PTRCALL, but for low number of arguments.
inline - Used for selected internal functions for which inlining
may improve performance on some platforms.
Note: Use of these macros is based on judgement, not hard rules,
and therefore subject to change.
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2018 Yury Gribov <tetra2005@gmail.com>
Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#if defined(__GNUC__) && defined(__i386__) && !defined(__MINGW32__)
/* We'll use this version by default only where we know it helps.
regparm() generates warnings on Solaris boxes. See SF bug #692878.
Instability reported with egcs on a RedHat Linux 7.3.
Let's comment out:
#define FASTCALL __attribute__((stdcall, regparm(3)))
and let's try this:
*/
#define FASTCALL __attribute__((regparm(3)))
#define PTRFASTCALL __attribute__((regparm(3)))
#endif
/* Using __fastcall seems to have an unexpected negative effect under
MS VC++, especially for function pointers, so we won't use it for
now on that platform. It may be reconsidered for a future release
if it can be made more effective.
Likely reason: __fastcall on Windows is like stdcall, therefore
the compiler cannot perform stack optimizations for call clusters.
*/
/* Make sure all of these are defined if they aren't already. */
#ifndef FASTCALL
#define FASTCALL
#endif
#ifndef PTRCALL
#define PTRCALL
#endif
#ifndef PTRFASTCALL
#define PTRFASTCALL
#endif
#ifndef XML_MIN_SIZE
#if !defined(__cplusplus) && !defined(inline)
#ifdef __GNUC__
#define inline __inline
#endif /* __GNUC__ */
#endif
#endif /* XML_MIN_SIZE */
#ifdef __cplusplus
#define inline inline
#else
#ifndef inline
#define inline
#endif
#endif
#include <limits.h> // ULONG_MAX
#include <stddef.h> // size_t
#if defined(_WIN32) && (!defined(__USE_MINGW_ANSI_STDIO) || (1 - __USE_MINGW_ANSI_STDIO - 1 == 0))
#define EXPAT_FMT_ULL(midpart) "%" midpart "I64u"
#if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW
#define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d"
#define EXPAT_FMT_SIZE_T(midpart) "%" midpart "I64u"
#else
#define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d"
#define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
#endif
#else
#define EXPAT_FMT_ULL(midpart) "%" midpart "llu"
#if !defined(ULONG_MAX)
#error Compiler did not define ULONG_MAX for us
#elif ULONG_MAX == 18446744073709551615u // 2^64-1
#define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld"
#define EXPAT_FMT_SIZE_T(midpart) "%" midpart "lu"
#elif defined(EMSCRIPTEN) // 32bit mode Emscripten
#define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld"
#define EXPAT_FMT_SIZE_T(midpart) "%" midpart "zu"
#else
#define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d"
#define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
#endif
#endif
#ifndef UNUSED_P
#define UNUSED_P(p) (void)p
#endif
/* NOTE BEGIN If you ever patch these defaults to greater values
for non-attack XML payload in your environment,
please file a bug report with libexpat. Thank you!
*/
#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT 100.0f
#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT 8388608 // 8 MiB, 2^23
#define EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT 100.0f
#define EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT 67108864 // 64 MiB, 2^26
// NOTE: If function expat_alloc was user facing, EXPAT_MALLOC_ALIGNMENT would
// have to take sizeof(long double) into account
#define EXPAT_MALLOC_ALIGNMENT sizeof(long long) // largest parser (sub)member
#define EXPAT_MALLOC_PADDING ((EXPAT_MALLOC_ALIGNMENT) - sizeof(size_t))
/* NOTE END */
#include "expat.h" // so we can use type XML_Parser below
#ifdef __cplusplus
extern "C" {
#endif
void _INTERNAL_trim_to_complete_utf8_characters(const char* from, const char** fromLimRef);
#if defined(XML_GE) && XML_GE == 1
unsigned long long testingAccountingGetCountBytesDirect(XML_Parser parser);
unsigned long long testingAccountingGetCountBytesIndirect(XML_Parser parser);
const char* unsignedCharToPrintable(unsigned char c);
#endif
extern
#if !defined(XML_TESTING)
const
#endif
XML_Bool g_reparseDeferralEnabledDefault; // written ONLY in runtests.c
#if defined(XML_TESTING)
void* expat_malloc(XML_Parser parser, size_t size, int sourceLine);
void expat_free(XML_Parser parser, void* ptr, int sourceLine);
void* expat_realloc(XML_Parser parser, void* ptr, size_t size, int sourceLine);
extern unsigned int g_bytesScanned; // used for testing only
#endif
#ifdef __cplusplus
}
#endif
-66
View File
@@ -1,66 +0,0 @@
/*
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-84
View File
@@ -1,84 +0,0 @@
; DEF file for MS VC++
EXPORTS
XML_DefaultCurrent @1
XML_ErrorString @2
XML_ExpatVersion @3
XML_ExpatVersionInfo @4
XML_ExternalEntityParserCreate @5
XML_GetBase @6
XML_GetBuffer @7
XML_GetCurrentByteCount @8
XML_GetCurrentByteIndex @9
XML_GetCurrentColumnNumber @10
XML_GetCurrentLineNumber @11
XML_GetErrorCode @12
XML_GetIdAttributeIndex @13
XML_GetInputContext @14
XML_GetSpecifiedAttributeCount @15
XML_Parse @16
XML_ParseBuffer @17
XML_ParserCreate @18
XML_ParserCreateNS @19
XML_ParserCreate_MM @20
XML_ParserFree @21
XML_SetAttlistDeclHandler @22
XML_SetBase @23
XML_SetCdataSectionHandler @24
XML_SetCharacterDataHandler @25
XML_SetCommentHandler @26
XML_SetDefaultHandler @27
XML_SetDefaultHandlerExpand @28
XML_SetDoctypeDeclHandler @29
XML_SetElementDeclHandler @30
XML_SetElementHandler @31
XML_SetEncoding @32
XML_SetEndCdataSectionHandler @33
XML_SetEndDoctypeDeclHandler @34
XML_SetEndElementHandler @35
XML_SetEndNamespaceDeclHandler @36
XML_SetEntityDeclHandler @37
XML_SetExternalEntityRefHandler @38
XML_SetExternalEntityRefHandlerArg @39
XML_SetNamespaceDeclHandler @40
XML_SetNotStandaloneHandler @41
XML_SetNotationDeclHandler @42
XML_SetParamEntityParsing @43
XML_SetProcessingInstructionHandler @44
XML_SetReturnNSTriplet @45
XML_SetStartCdataSectionHandler @46
XML_SetStartDoctypeDeclHandler @47
XML_SetStartElementHandler @48
XML_SetStartNamespaceDeclHandler @49
XML_SetUnknownEncodingHandler @50
XML_SetUnparsedEntityDeclHandler @51
XML_SetUserData @52
XML_SetXmlDeclHandler @53
XML_UseParserAsHandlerArg @54
; added with version 1.95.3
XML_ParserReset @55
XML_SetSkippedEntityHandler @56
; added with version 1.95.5
XML_GetFeatureList @57
XML_UseForeignDTD @58
; added with version 1.95.6
XML_FreeContentModel @59
XML_MemMalloc @60
XML_MemRealloc @61
XML_MemFree @62
; added with version 1.95.8
XML_StopParser @63
XML_ResumeParser @64
XML_GetParsingStatus @65
; added with version 2.1.1
@_EXPAT_COMMENT_ATTR_INFO@ XML_GetAttributeInfo @66
XML_SetHashSalt @67
; internal @68 removed with version 2.3.1
; added with version 2.4.0
@_EXPAT_COMMENT_DTD_OR_GE@ XML_SetBillionLaughsAttackProtectionActivationThreshold @69
@_EXPAT_COMMENT_DTD_OR_GE@ XML_SetBillionLaughsAttackProtectionMaximumAmplification @70
; added with version 2.6.0
XML_SetReparseDeferralEnabled @71
; added with version 2.7.2
@_EXPAT_COMMENT_DTD_OR_GE@ XML_SetAllocTrackerMaximumAmplification @72
@_EXPAT_COMMENT_DTD_OR_GE@ XML_SetAllocTrackerActivationThreshold @73
-11
View File
@@ -1,11 +0,0 @@
{
"name": "expat",
"version": "2.7.3",
"build": {
"srcFilter": [
"+<xmlparse.c>",
"+<xmlrole.c>",
"+<xmltok.c>"
]
}
}
-102
View File
@@ -1,102 +0,0 @@
/*
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
static const unsigned namingBitmap[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x04000000,
0x87FFFFFE, 0x07FFFFFE, 0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, 0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE,
0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFD740,
0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, 0xFFFF0003, 0xFFFFFFFF,
0xFFFF199F, 0x033FCFFF, 0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, 0x0000007F, 0x00000000, 0xFFFF0000,
0x000707FF, 0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, 0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060,
0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, 0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, 0xFFF987E0,
0x036DFDFF, 0x5E000000, 0x001C0000, 0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, 0xFFF99FE0, 0x23CDFDFF,
0xB0000000, 0x00000003, 0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, 0xFFFDDFE0, 0x03EFFDFF, 0x00000000,
0x00000003, 0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, 0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, 0xFEF02596,
0x200D6CAE, 0x0000001F, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFF003F,
0x007FFFFF, 0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, 0x40000000, 0xF580C900, 0x00000007, 0x02010800,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, 0x3F3FFFFF,
0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, 0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, 0x00000000, 0x00004C40,
0x00000000, 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000080, 0x000003FE, 0xFFFFFFFE,
0xFFFFFFFF, 0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, 0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x0000003F, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000000F,
0x00000000, 0x00000000, 0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, 0x00000000, 0x00800000, 0xFF7FFFFF,
0xFF7FFFFF, 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, 0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, 0xFFFFDFFE,
0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, 0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, 0x00000000, 0xFFFE0000,
0x027FFFFF, 0xFFFFFFFE, 0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, 0x00000000, 0x07FFFFFE, 0x0007FFFF,
0xFFFF03FF, 0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, 0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF,
0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, 0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, 0xFFFBAFEE,
0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, 0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, 0xD63DC7EC, 0xC3BFC718,
0x00803DC7, 0x0000FF80, 0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, 0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF,
0x0000FFC3, 0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, 0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, 0x03000000,
0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, 0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, 0x000000A0, 0x003EFFFE, 0xFFFFFFFE,
0xFFFFFFFF, 0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF,
};
static const unsigned char nmstrtPages[] = {
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char namePages[] = {
0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, 0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x10, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x26, 0x14, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
-379
View File
@@ -1,379 +0,0 @@
/* ==========================================================================
* siphash.h - SipHash-2-4 in a single header file
* --------------------------------------------------------------------------
* Derived by William Ahern from the reference implementation[1] published[2]
* by Jean-Philippe Aumasson and Daniel J. Berstein.
* Minimal changes by Sebastian Pipping and Victor Stinner on top, see below.
* Licensed under the CC0 Public Domain Dedication license.
*
* 1. https://www.131002.net/siphash/siphash24.c
* 2. https://www.131002.net/siphash/
* --------------------------------------------------------------------------
* HISTORY:
*
* 2020-10-03 (Sebastian Pipping)
* - Drop support for Visual Studio 9.0/2008 and earlier
*
* 2019-08-03 (Sebastian Pipping)
* - Mark part of sip24_valid as to be excluded from clang-format
* - Re-format code using clang-format 9
*
* 2018-07-08 (Anton Maklakov)
* - Add "fall through" markers for GCC's -Wimplicit-fallthrough
*
* 2017-11-03 (Sebastian Pipping)
* - Hide sip_tobin and sip_binof unless SIPHASH_TOBIN macro is defined
*
* 2017-07-25 (Vadim Zeitlin)
* - Fix use of SIPHASH_MAIN macro
*
* 2017-07-05 (Sebastian Pipping)
* - Use _SIP_ULL macro to not require a C++11 compiler if compiled as C++
* - Add const qualifiers at two places
* - Ensure <=80 characters line length (assuming tab width 4)
*
* 2017-06-23 (Victor Stinner)
* - Address Win64 compile warnings
*
* 2017-06-18 (Sebastian Pipping)
* - Clarify license note in the header
* - Address C89 issues:
* - Stop using inline keyword (and let compiler decide)
* - Replace _Bool by int
* - Turn macro siphash24 into a function
* - Address invalid conversion (void pointer) by explicit cast
* - Address lack of stdint.h for Visual Studio 2003 to 2008
* - Always expose sip24_valid (for self-tests)
*
* 2012-11-04 - Born. (William Ahern)
* --------------------------------------------------------------------------
* USAGE:
*
* SipHash-2-4 takes as input two 64-bit words as the key, some number of
* message bytes, and outputs a 64-bit word as the message digest. This
* implementation employs two data structures: a struct sipkey for
* representing the key, and a struct siphash for representing the hash
* state.
*
* For converting a 16-byte unsigned char array to a key, use either the
* macro sip_keyof or the routine sip_tokey. The former instantiates a
* compound literal key, while the latter requires a key object as a
* parameter.
*
* unsigned char secret[16];
* arc4random_buf(secret, sizeof secret);
* struct sipkey *key = sip_keyof(secret);
*
* For hashing a message, use either the convenience macro siphash24 or the
* routines sip24_init, sip24_update, and sip24_final.
*
* struct siphash state;
* void *msg;
* size_t len;
* uint64_t hash;
*
* sip24_init(&state, key);
* sip24_update(&state, msg, len);
* hash = sip24_final(&state);
*
* or
*
* hash = siphash24(msg, len, key);
*
* To convert the 64-bit hash value to a canonical 8-byte little-endian
* binary representation, use either the macro sip_binof or the routine
* sip_tobin. The former instantiates and returns a compound literal array,
* while the latter requires an array object as a parameter.
* --------------------------------------------------------------------------
* NOTES:
*
* o Neither sip_keyof, sip_binof, nor siphash24 will work with compilers
* lacking compound literal support. Instead, you must use the lower-level
* interfaces which take as parameters the temporary state objects.
*
* o Uppercase macros may evaluate parameters more than once. Lowercase
* macros should not exhibit any such side effects.
* ==========================================================================
*/
#ifndef SIPHASH_H
#define SIPHASH_H
#include <stddef.h> /* size_t */
#include <stdint.h> /* uint64_t uint32_t uint8_t */
/*
* Workaround to not require a C++11 compiler for using ULL suffix
* if this code is included and compiled as C++; related GCC warning is:
* warning: use of C++11 long long integer constant [-Wlong-long]
*/
#define SIP_ULL(high, low) ((((uint64_t)high) << 32) | (low))
#define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
#define SIP_U32TO8_LE(p, v) \
(p)[0] = (uint8_t)((v) >> 0); \
(p)[1] = (uint8_t)((v) >> 8); \
(p)[2] = (uint8_t)((v) >> 16); \
(p)[3] = (uint8_t)((v) >> 24);
#define SIP_U64TO8_LE(p, v) \
SIP_U32TO8_LE((p) + 0, (uint32_t)((v) >> 0)); \
SIP_U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
#define SIP_U8TO64_LE(p) \
(((uint64_t)((p)[0]) << 0) | ((uint64_t)((p)[1]) << 8) | ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
#define SIPHASH_INITIALIZER {0, 0, 0, 0, {0}, 0, 0}
struct siphash {
uint64_t v0, v1, v2, v3;
unsigned char buf[8], *p;
uint64_t c;
}; /* struct siphash */
#define SIP_KEYLEN 16
struct sipkey {
uint64_t k[2];
}; /* struct sipkey */
#define sip_keyof(k) sip_tokey(&(struct sipkey){{0}}, (k))
static struct sipkey* sip_tokey(struct sipkey* key, const void* src) {
key->k[0] = SIP_U8TO64_LE((const unsigned char*)src);
key->k[1] = SIP_U8TO64_LE((const unsigned char*)src + 8);
return key;
} /* sip_tokey() */
#ifdef SIPHASH_TOBIN
#define sip_binof(v) sip_tobin((unsigned char[8]){0}, (v))
static void* sip_tobin(void* dst, uint64_t u64) {
SIP_U64TO8_LE((unsigned char*)dst, u64);
return dst;
} /* sip_tobin() */
#endif /* SIPHASH_TOBIN */
static void sip_round(struct siphash* H, const int rounds) {
int i;
for (i = 0; i < rounds; i++) {
H->v0 += H->v1;
H->v1 = SIP_ROTL(H->v1, 13);
H->v1 ^= H->v0;
H->v0 = SIP_ROTL(H->v0, 32);
H->v2 += H->v3;
H->v3 = SIP_ROTL(H->v3, 16);
H->v3 ^= H->v2;
H->v0 += H->v3;
H->v3 = SIP_ROTL(H->v3, 21);
H->v3 ^= H->v0;
H->v2 += H->v1;
H->v1 = SIP_ROTL(H->v1, 17);
H->v1 ^= H->v2;
H->v2 = SIP_ROTL(H->v2, 32);
}
} /* sip_round() */
static struct siphash* sip24_init(struct siphash* H, const struct sipkey* key) {
H->v0 = SIP_ULL(0x736f6d65U, 0x70736575U) ^ key->k[0];
H->v1 = SIP_ULL(0x646f7261U, 0x6e646f6dU) ^ key->k[1];
H->v2 = SIP_ULL(0x6c796765U, 0x6e657261U) ^ key->k[0];
H->v3 = SIP_ULL(0x74656462U, 0x79746573U) ^ key->k[1];
H->p = H->buf;
H->c = 0;
return H;
} /* sip24_init() */
#define sip_endof(a) (&(a)[sizeof(a) / sizeof *(a)])
static struct siphash* sip24_update(struct siphash* H, const void* src, size_t len) {
const unsigned char *p = (const unsigned char*)src, *pe = p + len;
uint64_t m;
do {
while (p < pe && H->p < sip_endof(H->buf)) *H->p++ = *p++;
if (H->p < sip_endof(H->buf)) break;
m = SIP_U8TO64_LE(H->buf);
H->v3 ^= m;
sip_round(H, 2);
H->v0 ^= m;
H->p = H->buf;
H->c += 8;
} while (p < pe);
return H;
} /* sip24_update() */
static uint64_t sip24_final(struct siphash* H) {
const char left = (char)(H->p - H->buf);
uint64_t b = (H->c + left) << 56;
switch (left) {
case 7:
b |= (uint64_t)H->buf[6] << 48;
/* fall through */
case 6:
b |= (uint64_t)H->buf[5] << 40;
/* fall through */
case 5:
b |= (uint64_t)H->buf[4] << 32;
/* fall through */
case 4:
b |= (uint64_t)H->buf[3] << 24;
/* fall through */
case 3:
b |= (uint64_t)H->buf[2] << 16;
/* fall through */
case 2:
b |= (uint64_t)H->buf[1] << 8;
/* fall through */
case 1:
b |= (uint64_t)H->buf[0] << 0;
/* fall through */
case 0:
break;
}
H->v3 ^= b;
sip_round(H, 2);
H->v0 ^= b;
H->v2 ^= 0xff;
sip_round(H, 4);
return H->v0 ^ H->v1 ^ H->v2 ^ H->v3;
} /* sip24_final() */
static uint64_t siphash24(const void* src, size_t len, const struct sipkey* key) {
struct siphash state = SIPHASH_INITIALIZER;
return sip24_final(sip24_update(sip24_init(&state, key), src, len));
} /* siphash24() */
/*
* SipHash-2-4 output with
* k = 00 01 02 ...
* and
* in = (empty string)
* in = 00 (1 byte)
* in = 00 01 (2 bytes)
* in = 00 01 02 (3 bytes)
* ...
* in = 00 01 02 ... 3e (63 bytes)
*/
static int sip24_valid(void) {
/* clang-format off */
static const unsigned char vectors[64][8] = {
{ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
{ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
{ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
{ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
{ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
{ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
{ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
{ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
{ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
{ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
{ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
{ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
{ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
{ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
{ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
{ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
{ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
{ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
{ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
{ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
{ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
{ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
{ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
{ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
{ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
{ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
{ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
{ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
{ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
{ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
{ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
{ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
{ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
{ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
{ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
{ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
{ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
{ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
{ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
{ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
{ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
{ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
{ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
{ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
{ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
{ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
{ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
{ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
{ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
{ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
{ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
{ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
{ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
{ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
{ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
{ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
{ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
{ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
{ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
{ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
{ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
{ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
{ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
{ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
};
/* clang-format on */
unsigned char in[64];
struct sipkey k;
size_t i;
sip_tokey(&k,
"\000\001\002\003\004\005\006\007\010\011"
"\012\013\014\015\016\017");
for (i = 0; i < sizeof in; ++i) {
in[i] = (unsigned char)i;
if (siphash24(in, i, &k) != SIP_U8TO64_LE(vectors[i])) return 0;
}
return 1;
} /* sip24_valid() */
#ifdef SIPHASH_MAIN
#include <stdio.h>
int main(void) {
const int ok = sip24_valid();
if (ok)
puts("OK");
else
puts("FAIL");
return !ok;
} /* main() */
#endif /* SIPHASH_MAIN */
#endif /* SIPHASH_H */
-66
View File
@@ -1,66 +0,0 @@
/*
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
-48
View File
@@ -1,48 +0,0 @@
/*
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2017-2023 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2023 Orgad Shaneh <orgad.shaneh@audiocodes.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef WINCONFIG_H
#define WINCONFIG_H
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <memory.h>
#include <string.h>
#endif /* ndef WINCONFIG_H */
-8210
View File
File diff suppressed because it is too large Load Diff
-1108
View File
File diff suppressed because it is too large Load Diff
-134
View File
@@ -1,134 +0,0 @@
/*
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2017-2025 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef XmlRole_INCLUDED
#define XmlRole_INCLUDED 1
#include "xmltok.h"
#ifdef __cplusplus
extern "C" {
#endif
enum {
XML_ROLE_ERROR = -1,
XML_ROLE_NONE = 0,
XML_ROLE_XML_DECL,
XML_ROLE_INSTANCE_START,
XML_ROLE_DOCTYPE_NONE,
XML_ROLE_DOCTYPE_NAME,
XML_ROLE_DOCTYPE_SYSTEM_ID,
XML_ROLE_DOCTYPE_PUBLIC_ID,
XML_ROLE_DOCTYPE_INTERNAL_SUBSET,
XML_ROLE_DOCTYPE_CLOSE,
XML_ROLE_GENERAL_ENTITY_NAME,
XML_ROLE_PARAM_ENTITY_NAME,
XML_ROLE_ENTITY_NONE,
XML_ROLE_ENTITY_VALUE,
XML_ROLE_ENTITY_SYSTEM_ID,
XML_ROLE_ENTITY_PUBLIC_ID,
XML_ROLE_ENTITY_COMPLETE,
XML_ROLE_ENTITY_NOTATION_NAME,
XML_ROLE_NOTATION_NONE,
XML_ROLE_NOTATION_NAME,
XML_ROLE_NOTATION_SYSTEM_ID,
XML_ROLE_NOTATION_NO_SYSTEM_ID,
XML_ROLE_NOTATION_PUBLIC_ID,
XML_ROLE_ATTRIBUTE_NAME,
XML_ROLE_ATTRIBUTE_TYPE_CDATA,
XML_ROLE_ATTRIBUTE_TYPE_ID,
XML_ROLE_ATTRIBUTE_TYPE_IDREF,
XML_ROLE_ATTRIBUTE_TYPE_IDREFS,
XML_ROLE_ATTRIBUTE_TYPE_ENTITY,
XML_ROLE_ATTRIBUTE_TYPE_ENTITIES,
XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN,
XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS,
XML_ROLE_ATTRIBUTE_ENUM_VALUE,
XML_ROLE_ATTRIBUTE_NOTATION_VALUE,
XML_ROLE_ATTLIST_NONE,
XML_ROLE_ATTLIST_ELEMENT_NAME,
XML_ROLE_IMPLIED_ATTRIBUTE_VALUE,
XML_ROLE_REQUIRED_ATTRIBUTE_VALUE,
XML_ROLE_DEFAULT_ATTRIBUTE_VALUE,
XML_ROLE_FIXED_ATTRIBUTE_VALUE,
XML_ROLE_ELEMENT_NONE,
XML_ROLE_ELEMENT_NAME,
XML_ROLE_CONTENT_ANY,
XML_ROLE_CONTENT_EMPTY,
XML_ROLE_CONTENT_PCDATA,
XML_ROLE_GROUP_OPEN,
XML_ROLE_GROUP_CLOSE,
XML_ROLE_GROUP_CLOSE_REP,
XML_ROLE_GROUP_CLOSE_OPT,
XML_ROLE_GROUP_CLOSE_PLUS,
XML_ROLE_GROUP_CHOICE,
XML_ROLE_GROUP_SEQUENCE,
XML_ROLE_CONTENT_ELEMENT,
XML_ROLE_CONTENT_ELEMENT_REP,
XML_ROLE_CONTENT_ELEMENT_OPT,
XML_ROLE_CONTENT_ELEMENT_PLUS,
XML_ROLE_PI,
XML_ROLE_COMMENT,
#ifdef XML_DTD
XML_ROLE_TEXT_DECL,
XML_ROLE_IGNORE_SECT,
XML_ROLE_INNER_PARAM_ENTITY_REF,
#endif /* XML_DTD */
XML_ROLE_PARAM_ENTITY_REF
};
typedef struct prolog_state {
int(PTRCALL* handler)(struct prolog_state* state, int tok, const char* ptr, const char* end, const ENCODING* enc);
unsigned level;
int role_none;
#ifdef XML_DTD
unsigned includeLevel;
int documentEntity;
int inEntityValue;
#endif /* XML_DTD */
} PROLOG_STATE;
void XmlPrologStateInit(PROLOG_STATE* state);
#ifdef XML_DTD
void XmlPrologStateInitExternalEntity(PROLOG_STATE* state);
#endif /* XML_DTD */
#define XmlTokenRole(state, tok, ptr, end, enc) (((state)->handler)(state, tok, ptr, end, enc))
#ifdef __cplusplus
}
#endif
#endif /* not XmlRole_INCLUDED */
-1489
View File
File diff suppressed because it is too large Load Diff
-288
View File
@@ -1,288 +0,0 @@
/*
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2002-2005 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef XmlTok_INCLUDED
#define XmlTok_INCLUDED 1
#ifdef __cplusplus
extern "C" {
#endif
/* The following token may be returned by XmlContentTok */
#define XML_TOK_TRAILING_RSQB \
-5 /* ] or ]] at the end of the scan; might be \
start of illegal ]]> sequence */
/* The following tokens may be returned by both XmlPrologTok and
XmlContentTok.
*/
#define XML_TOK_NONE -4 /* The string to be scanned is empty */
#define XML_TOK_TRAILING_CR \
-3 /* A CR at the end of the scan; \
might be part of CRLF sequence */
#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
#define XML_TOK_PARTIAL -1 /* only part of a token */
#define XML_TOK_INVALID 0
/* The following tokens are returned by XmlContentTok; some are also
returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok.
*/
#define XML_TOK_START_TAG_WITH_ATTS 1
#define XML_TOK_START_TAG_NO_ATTS 2
#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
#define XML_TOK_END_TAG 5
#define XML_TOK_DATA_CHARS 6
#define XML_TOK_DATA_NEWLINE 7
#define XML_TOK_CDATA_SECT_OPEN 8
#define XML_TOK_ENTITY_REF 9
#define XML_TOK_CHAR_REF 10 /* numeric character reference */
/* The following tokens may be returned by both XmlPrologTok and
XmlContentTok.
*/
#define XML_TOK_PI 11 /* processing instruction */
#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
#define XML_TOK_COMMENT 13
#define XML_TOK_BOM 14 /* Byte order mark */
/* The following tokens are returned only by XmlPrologTok */
#define XML_TOK_PROLOG_S 15
#define XML_TOK_DECL_OPEN 16 /* <!foo */
#define XML_TOK_DECL_CLOSE 17 /* > */
#define XML_TOK_NAME 18
#define XML_TOK_NMTOKEN 19
#define XML_TOK_POUND_NAME 20 /* #name */
#define XML_TOK_OR 21 /* | */
#define XML_TOK_PERCENT 22
#define XML_TOK_OPEN_PAREN 23
#define XML_TOK_CLOSE_PAREN 24
#define XML_TOK_OPEN_BRACKET 25
#define XML_TOK_CLOSE_BRACKET 26
#define XML_TOK_LITERAL 27
#define XML_TOK_PARAM_ENTITY_REF 28
#define XML_TOK_INSTANCE_START 29
/* The following occur only in element type declarations */
#define XML_TOK_NAME_QUESTION 30 /* name? */
#define XML_TOK_NAME_ASTERISK 31 /* name* */
#define XML_TOK_NAME_PLUS 32 /* name+ */
#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
#define XML_TOK_COMMA 38
/* The following token is returned only by XmlAttributeValueTok */
#define XML_TOK_ATTRIBUTE_VALUE_S 39
/* The following token is returned only by XmlCdataSectionTok */
#define XML_TOK_CDATA_SECT_CLOSE 40
/* With namespace processing this is returned by XmlPrologTok for a
name with a colon.
*/
#define XML_TOK_PREFIXED_NAME 41
#ifdef XML_DTD
#define XML_TOK_IGNORE_SECT 42
#endif /* XML_DTD */
#ifdef XML_DTD
#define XML_N_STATES 4
#else /* not XML_DTD */
#define XML_N_STATES 3
#endif /* not XML_DTD */
#define XML_PROLOG_STATE 0
#define XML_CONTENT_STATE 1
#define XML_CDATA_SECTION_STATE 2
#ifdef XML_DTD
#define XML_IGNORE_SECTION_STATE 3
#endif /* XML_DTD */
#define XML_N_LITERAL_TYPES 2
#define XML_ATTRIBUTE_VALUE_LITERAL 0
#define XML_ENTITY_VALUE_LITERAL 1
/* The size of the buffer passed to XmlUtf8Encode must be at least this. */
#define XML_UTF8_ENCODE_MAX 4
/* The size of the buffer passed to XmlUtf16Encode must be at least this. */
#define XML_UTF16_ENCODE_MAX 2
typedef struct position {
/* first line and first column are 0 not 1 */
XML_Size lineNumber;
XML_Size columnNumber;
} POSITION;
typedef struct {
const char* name;
const char* valuePtr;
const char* valueEnd;
char normalized;
} ATTRIBUTE;
struct encoding;
typedef struct encoding ENCODING;
typedef int(PTRCALL* SCANNER)(const ENCODING*, const char*, const char*, const char**);
enum XML_Convert_Result {
XML_CONVERT_COMPLETED = 0,
XML_CONVERT_INPUT_INCOMPLETE = 1,
XML_CONVERT_OUTPUT_EXHAUSTED = 2 /* and therefore potentially input remaining as well */
};
struct encoding {
SCANNER scanners[XML_N_STATES];
SCANNER literalScanners[XML_N_LITERAL_TYPES];
int(PTRCALL* nameMatchesAscii)(const ENCODING*, const char*, const char*, const char*);
int(PTRFASTCALL* nameLength)(const ENCODING*, const char*);
const char*(PTRFASTCALL* skipS)(const ENCODING*, const char*);
int(PTRCALL* getAtts)(const ENCODING* enc, const char* ptr, int attsMax, ATTRIBUTE* atts);
int(PTRFASTCALL* charRefNumber)(const ENCODING* enc, const char* ptr);
int(PTRCALL* predefinedEntityName)(const ENCODING*, const char*, const char*);
void(PTRCALL* updatePosition)(const ENCODING*, const char* ptr, const char* end, POSITION*);
int(PTRCALL* isPublicId)(const ENCODING* enc, const char* ptr, const char* end, const char** badPtr);
enum XML_Convert_Result(PTRCALL* utf8Convert)(const ENCODING* enc, const char** fromP, const char* fromLim,
char** toP, const char* toLim);
enum XML_Convert_Result(PTRCALL* utf16Convert)(const ENCODING* enc, const char** fromP, const char* fromLim,
unsigned short** toP, const unsigned short* toLim);
int minBytesPerChar;
char isUtf8;
char isUtf16;
};
/* Scan the string starting at ptr until the end of the next complete
token, but do not scan past eptr. Return an integer giving the
type of token.
Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set.
Return XML_TOK_PARTIAL when the string does not contain a complete
token; nextTokPtr will not be set.
Return XML_TOK_INVALID when the string does not start a valid
token; nextTokPtr will be set to point to the character which made
the token invalid.
Otherwise the string starts with a valid token; nextTokPtr will be
set to point to the character following the end of that token.
Each data character counts as a single token, but adjacent data
characters may be returned together. Similarly for characters in
the prolog outside literals, comments and processing instructions.
*/
#define XmlTok(enc, state, ptr, end, nextTokPtr) (((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
#define XmlPrologTok(enc, ptr, end, nextTokPtr) XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
#define XmlContentTok(enc, ptr, end, nextTokPtr) XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
#ifdef XML_DTD
#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
#endif /* XML_DTD */
/* This is used for performing a 2nd-level tokenization on the content
of a literal that has already been returned by XmlTok.
*/
#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
(((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2))
#define XmlNameLength(enc, ptr) (((enc)->nameLength)(enc, ptr))
#define XmlSkipS(enc, ptr) (((enc)->skipS)(enc, ptr))
#define XmlGetAttributes(enc, ptr, attsMax, atts) (((enc)->getAtts)(enc, ptr, attsMax, atts))
#define XmlCharRefNumber(enc, ptr) (((enc)->charRefNumber)(enc, ptr))
#define XmlPredefinedEntityName(enc, ptr, end) (((enc)->predefinedEntityName)(enc, ptr, end))
#define XmlUpdatePosition(enc, ptr, end, pos) (((enc)->updatePosition)(enc, ptr, end, pos))
#define XmlIsPublicId(enc, ptr, end, badPtr) (((enc)->isPublicId)(enc, ptr, end, badPtr))
#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
typedef struct {
ENCODING initEnc;
const ENCODING** encPtr;
} INIT_ENCODING;
int XmlParseXmlDecl(int isGeneralTextEntity, const ENCODING* enc, const char* ptr, const char* end, const char** badPtr,
const char** versionPtr, const char** versionEndPtr, const char** encodingNamePtr,
const ENCODING** namedEncodingPtr, int* standalonePtr);
int XmlInitEncoding(INIT_ENCODING* p, const ENCODING** encPtr, const char* name);
const ENCODING* XmlGetUtf8InternalEncoding(void);
const ENCODING* XmlGetUtf16InternalEncoding(void);
int FASTCALL XmlUtf8Encode(int charNumber, char* buf);
int FASTCALL XmlUtf16Encode(int charNumber, unsigned short* buf);
int XmlSizeOfUnknownEncoding(void);
typedef int(XMLCALL* CONVERTER)(void* userData, const char* p);
ENCODING* XmlInitUnknownEncoding(void* mem, const int* table, CONVERTER convert, void* userData);
int XmlParseXmlDeclNS(int isGeneralTextEntity, const ENCODING* enc, const char* ptr, const char* end,
const char** badPtr, const char** versionPtr, const char** versionEndPtr,
const char** encodingNamePtr, const ENCODING** namedEncodingPtr, int* standalonePtr);
int XmlInitEncodingNS(INIT_ENCODING* p, const ENCODING** encPtr, const char* name);
const ENCODING* XmlGetUtf8InternalEncodingNS(void);
const ENCODING* XmlGetUtf16InternalEncodingNS(void);
ENCODING* XmlInitUnknownEncodingNS(void* mem, const int* table, CONVERTER convert, void* userData);
#ifdef __cplusplus
}
#endif
#endif /* not XmlTok_INCLUDED */
File diff suppressed because it is too large Load Diff
-74
View File
@@ -1,74 +0,0 @@
/*
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2017-2019 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
enum {
BT_NONXML, /* e.g. noncharacter-FFFF */
BT_MALFORM, /* illegal, with regard to encoding */
BT_LT, /* less than = "<" */
BT_AMP, /* ampersand = "&" */
BT_RSQB, /* right square bracket = "[" */
BT_LEAD2, /* lead byte of a 2-byte UTF-8 character */
BT_LEAD3, /* lead byte of a 3-byte UTF-8 character */
BT_LEAD4, /* lead byte of a 4-byte UTF-8 character */
BT_TRAIL, /* trailing unit, e.g. second 16-bit unit of a 4-byte char. */
BT_CR, /* carriage return = "\r" */
BT_LF, /* line feed = "\n" */
BT_GT, /* greater than = ">" */
BT_QUOT, /* quotation character = "\"" */
BT_APOS, /* apostrophe = "'" */
BT_EQUALS, /* equal sign = "=" */
BT_QUEST, /* question mark = "?" */
BT_EXCL, /* exclamation mark = "!" */
BT_SOL, /* solidus, slash = "/" */
BT_SEMI, /* semicolon = ";" */
BT_NUM, /* number sign = "#" */
BT_LSQB, /* left square bracket = "[" */
BT_S, /* white space, e.g. "\t", " "[, "\r"] */
BT_NMSTRT, /* non-hex name start letter = "G".."Z" + "g".."z" + "_" */
BT_COLON, /* colon = ":" */
BT_HEX, /* hex letter = "A".."F" + "a".."f" */
BT_DIGIT, /* digit = "0".."9" */
BT_NAME, /* dot and middle dot = "." + chr(0xb7) */
BT_MINUS, /* minus = "-" */
BT_OTHER, /* known not to be a name or name start character */
BT_NONASCII, /* might be a name or name start character */
BT_PERCNT, /* percent sign = "%" */
BT_LPAR, /* left parenthesis = "(" */
BT_RPAR, /* right parenthesis = "(" */
BT_AST, /* asterisk = "*" */
BT_PLUS, /* plus sign = "+" */
BT_COMMA, /* comma = "," */
BT_VERBAR /* vertical bar = "|" */
};
#include <stddef.h>
-98
View File
@@ -1,98 +0,0 @@
/* This file is included!
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
| __// \| |_) | (_| | |_
\___/_/\_\ .__/ \__,_|\__|
|_| XML parser
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2017-2021 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef XML_TOK_NS_C
const ENCODING* NS(XmlGetUtf8InternalEncoding)(void) { return &ns(internal_utf8_encoding).enc; }
const ENCODING* NS(XmlGetUtf16InternalEncoding)(void) {
#if BYTEORDER == 1234
return &ns(internal_little2_encoding).enc;
#elif BYTEORDER == 4321
return &ns(internal_big2_encoding).enc;
#else
const short n = 1;
return (*(const char*)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc);
#endif
}
static const ENCODING* const NS(encodings)[] = {
&ns(latin1_encoding).enc, &ns(ascii_encoding).enc, &ns(utf8_encoding).enc, &ns(big2_encoding).enc,
&ns(big2_encoding).enc, &ns(little2_encoding).enc, &ns(utf8_encoding).enc /* NO_ENC */
};
static int PTRCALL NS(initScanProlog)(const ENCODING* enc, const char* ptr, const char* end, const char** nextTokPtr) {
return initScan(NS(encodings), (const INIT_ENCODING*)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr);
}
static int PTRCALL NS(initScanContent)(const ENCODING* enc, const char* ptr, const char* end, const char** nextTokPtr) {
return initScan(NS(encodings), (const INIT_ENCODING*)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr);
}
int NS(XmlInitEncoding)(INIT_ENCODING* p, const ENCODING** encPtr, const char* name) {
int i = getEncodingIndex(name);
if (i == UNKNOWN_ENC) return 0;
SET_INIT_ENC_INDEX(p, i);
p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
p->initEnc.updatePosition = initUpdatePosition;
p->encPtr = encPtr;
*encPtr = &(p->initEnc);
return 1;
}
static const ENCODING* NS(findEncoding)(const ENCODING* enc, const char* ptr, const char* end) {
#define ENCODING_MAX 128
char buf[ENCODING_MAX] = "";
char* p = buf;
int i;
XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1);
if (ptr != end) return 0;
*p = 0;
if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2) return enc;
i = getEncodingIndex(buf);
if (i == UNKNOWN_ENC) return 0;
return NS(encodings)[i];
}
int NS(XmlParseXmlDecl)(int isGeneralTextEntity, const ENCODING* enc, const char* ptr, const char* end,
const char** badPtr, const char** versionPtr, const char** versionEndPtr,
const char** encodingName, const ENCODING** encoding, int* standalone) {
return doParseXmlDecl(NS(findEncoding), isGeneralTextEntity, enc, ptr, end, badPtr, versionPtr, versionEndPtr,
encodingName, encoding, standalone);
}
#endif /* XML_TOK_NS_C */
+5 -3
View File
@@ -26,9 +26,6 @@ build_flags =
-DEINK_DISPLAY_SINGLE_BUFFER_MODE=1
-DDISABLE_FS_H_WARNING=1
-DDESTRUCTOR_CLOSES_FILE=1
# https://libexpat.github.io/doc/api/latest/#XML_GE
-DXML_GE=0
-DXML_CONTEXT_BYTES=1024
-std=gnu++2a
# Enable UTF-8 long file names in SdFat
-DUSE_UTF8_LONG_NAMES=1
@@ -37,6 +34,10 @@ build_flags =
-DPNG_MAX_BUFFERED_PIXELS=16416
-DFREEINK_DEVICE_X4=1
-DFREEINK_DEVICE_X3=1
# FreeInkBook memory profile for PSRAM-less ESP32-C3 (see BookProfile.h).
# The firmware's only expat is FreeInkBook's vendored copy (configured by its
# expat_config.h); consumers include <epub/Expat.h>.
-DFREEINK_BOOK_SMALL=1
-Wno-bidi-chars
-Wl,--wrap=panic_print_backtrace,--wrap=panic_abort,--wrap=bootloader_common_check_efuse_blk_validity
-fno-exceptions
@@ -67,6 +68,7 @@ lib_deps =
PowerManager=symlink://freeink-sdk/libs/hardware/PowerManager
FreeInkUI=symlink://freeink-sdk/libs/ui/FreeInkUI
Icons=symlink://freeink-sdk/libs/assets/Icons
FreeInkBook=symlink://freeink-sdk/libs/book/FreeInkBook
bblanchon/ArduinoJson @ 7.4.2
ricmoo/QRCode @ 0.0.1
bitbank2/PNGdec @ 1.1.6
+6 -4
View File
@@ -351,10 +351,12 @@ int CrossPointSettings::getRefreshFrequency() const {
}
}
int CrossPointSettings::getReaderFontId() const {
int CrossPointSettings::getReaderFontId() const { return getReaderFontId(fontSize); }
int CrossPointSettings::getReaderFontId(const uint8_t sizeIndex) const {
// Check SD card font first
if (sdFontFamilyName[0] != '\0' && sdFontIdResolver) {
int id = sdFontIdResolver(sdFontResolverCtx, sdFontFamilyName, fontSize);
int id = sdFontIdResolver(sdFontResolverCtx, sdFontFamilyName, sizeIndex);
if (id != 0) return id;
// Fall through to built-in if SD font not found
}
@@ -362,7 +364,7 @@ int CrossPointSettings::getReaderFontId() const {
switch (fontFamily) {
case NOTOSERIF:
default:
switch (fontSize) {
switch (sizeIndex) {
case SMALL:
return NOTOSERIF_12_FONT_ID;
case MEDIUM:
@@ -374,7 +376,7 @@ int CrossPointSettings::getReaderFontId() const {
return NOTOSERIF_18_FONT_ID;
}
case NOTOSANS:
switch (fontSize) {
switch (sizeIndex) {
case SMALL:
return NOTOSANS_12_FONT_ID;
case MEDIUM:
+4
View File
@@ -295,6 +295,10 @@ class CrossPointSettings {
return (shortPwrBtn == CrossPointSettings::SHORT_PWRBTN::SLEEP) ? 10 : 400;
}
int getReaderFontId() const;
// Same resolution (SD font first, then built-in family) for an explicit
// size rung — the FreeInkBook ladder needs all four sizes of the active
// family, not just the one the fontSize setting selects.
int getReaderFontId(uint8_t sizeIndex) const;
// If count_only is true, returns the number of settings items that would be written.
uint8_t writeSettings(HalFile& file, bool count_only = false) const;
+357
View File
@@ -0,0 +1,357 @@
#include "BookPaginator.h"
#include <Arduino.h>
#include <GfxRenderer.h>
#include <HalStorage.h>
#include <Logging.h>
#include <Memory.h>
#include <text/hyph_en_us.h>
#include <cstring>
#include "CrossPointSettings.h"
using freeink::book::Arena;
using freeink::book::BookStatus;
using freeink::book::ChapterLayout;
using freeink::book::CssStylesheetBuilder;
using freeink::book::ManifestItem;
using freeink::book::PageCacheWriter;
using freeink::book::TextAlign;
using freeink::book::ZipCatalog;
namespace {
// The .cpfont ladder: FONT_SIZE setting index -> pixel size. Must stay in
// step with the NOTOSERIF_12..18 / NOTOSANS_12..18 font registrations.
constexpr uint16_t kLadderPx[CrossPointSettings::FONT_SIZE_COUNT] = {12, 14, 16, 18};
uint32_t hashMix(uint32_t hash, uint32_t value) {
hash ^= value;
return hash * 16777619u;
}
// Forwards pages to the cache writer while surfacing build progress to the
// UI (indexing popup) every 16 pages.
class ProgressSink : public freeink::book::PageSink {
public:
ProgressSink(PageCacheWriter& writer, const BookPaginator::BuildProgress& progress)
: writer_(writer), progress_(progress) {}
void onAnchor(const uint32_t idHash, const uint32_t charStart) override { writer_.onAnchor(idHash, charStart); }
bool onPage(const freeink::book::Page& page) override {
const bool ok = writer_.onPage(page);
if (ok && progress_.fn != nullptr && (writer_.pageCount() & 15u) == 0) {
progress_.fn(progress_.ctx, writer_.pageCount());
}
return ok;
}
private:
PageCacheWriter& writer_;
BookPaginator::BuildProgress progress_;
};
} // namespace
bool BookPaginator::open(const std::string& path, const std::string& cacheDir, GfxRenderer& renderer) {
close();
bookBuf_ = makeUniqueNoThrow<uint8_t[]>(kBookArenaSize);
indexBuf_ = makeUniqueNoThrow<uint8_t[]>(kIndexArenaSize);
pageBuf_ = makeUniqueNoThrow<uint8_t[]>(kPageArenaSize);
sheetBuf_ = makeUniqueNoThrow<uint8_t[]>(kSheetArenaSize);
if (!bookBuf_ || !indexBuf_ || !pageBuf_ || !sheetBuf_) {
LOG_ERR("FIB", "OOM: paginator arenas (%u B)",
static_cast<unsigned>(kBookArenaSize + kIndexArenaSize + kPageArenaSize + kSheetArenaSize));
close();
return false;
}
bookArena_.init(bookBuf_.get(), kBookArenaSize);
indexArena_.init(indexBuf_.get(), kIndexArenaSize);
pageArena_.init(pageBuf_.get(), kPageArenaSize);
sheetArena_.init(sheetBuf_.get(), kSheetArenaSize);
if (!source_.open(path.c_str())) {
LOG_ERR("FIB", "Cannot open book file: %s", path.c_str());
close();
return false;
}
const size_t len = path.size();
isTxt_ = len > 4 && strcasecmp(path.c_str() + len - 4, ".txt") == 0;
if (!isTxt_) {
// Container open + book stylesheet need parse scratch; both are
// once-per-open, so the big build buffer is borrowed transiently.
auto scratchBuf = makeUniqueNoThrow<uint8_t[]>(kBuildScratchSize);
if (!scratchBuf) {
LOG_ERR("FIB", "OOM: open scratch (%u B)", static_cast<unsigned>(kBuildScratchSize));
close();
return false;
}
Arena scratch(scratchBuf.get(), kBuildScratchSize);
const BookStatus st = book_.open(source_, bookArena_, scratch);
if (st != BookStatus::Ok) {
LOG_ERR("FIB", "Book open failed: %d (%s)", static_cast<int>(st), path.c_str());
close();
return false;
}
CssStylesheetBuilder builder;
if (builder.begin(sheetArena_)) {
for (size_t m = 0; m < book_.manifestCount(); ++m) {
const ManifestItem* item = book_.manifestItem(m);
if (item == nullptr || item->mediaType == nullptr || strcmp(item->mediaType, "text/css") != 0) continue;
if (const freeink::book::ZipEntry* e = book_.zip().find(item->href)) {
builder.addSheet(source_, *e, scratch);
}
}
sheet_ = builder.finish();
if (builder.skippedSheets() > 0) {
LOG_INF("FIB", "%u stylesheet(s) skipped (size cap)", builder.skippedSheets());
}
}
}
cache_.setDir(cacheDir.c_str());
if (!buildFontChain(renderer)) {
close();
return false;
}
loadHyphenator();
open_ = true;
LOG_DBG("FIB", "Book open: %u spine items, book arena %u/%u B", static_cast<unsigned>(spineCount()),
static_cast<unsigned>(bookArena_.used()), static_cast<unsigned>(kBookArenaSize));
return true;
}
void BookPaginator::close() {
source_.close();
reader_ = freeink::book::PageCacheReader();
book_ = freeink::book::Book();
sheet_ = freeink::book::CssStylesheet{};
chain_ = freeink::book::FontChain();
hyphBlob_.reset();
bookBuf_.reset();
indexBuf_.reset();
pageBuf_.reset();
sheetBuf_.reset();
ladderCount_ = 0;
curSpine_ = kNoSpine;
open_ = false;
isTxt_ = false;
}
const char* BookPaginator::language() const {
if (!isTxt_ && book_.metadata().language != nullptr && book_.metadata().language[0] != '\0') {
return book_.metadata().language;
}
return "en";
}
bool BookPaginator::buildFontChain(GfxRenderer& renderer) {
static constexpr freeink::book::StyleFlags kChainFlags[4] = {
freeink::book::StyleNone,
freeink::book::StyleBold,
freeink::book::StyleItalic,
static_cast<freeink::book::StyleFlags>(freeink::book::StyleBold | freeink::book::StyleItalic),
};
ladderCount_ = 0;
const auto& fontMap = renderer.getFontMap();
for (uint8_t s = 0; s < CrossPointSettings::FONT_SIZE_COUNT; ++s) {
const int fontId = SETTINGS.getReaderFontId(s);
const auto it = fontMap.find(fontId);
if (it == fontMap.end()) {
LOG_ERR("FIB", "Reader font id %d (size %u px) not registered", fontId, kLadderPx[s]);
continue;
}
for (auto& adapter : adapters_) {
adapter.addSize(kLadderPx[s], &it->second);
}
ladderFontIds_[ladderCount_] = fontId;
ladderSizes_[ladderCount_] = kLadderPx[s];
++ladderCount_;
}
if (ladderCount_ == 0) {
LOG_ERR("FIB", "No reader fonts available");
return false;
}
for (uint8_t i = 0; i < 4; ++i) {
chain_.add(&adapters_[i], kChainFlags[i]);
}
return true;
}
void BookPaginator::loadHyphenator() {
if (!SETTINGS.hyphenationEnabled) return;
// Prefer language-specific patterns from the SD card (compiled with the
// SDK's tools/hyphc.py); English ships embedded in flash. A missing blob
// degrades to the embedded en-US patterns, which simply never match
// non-Latin words — text still lays out, just unhyphenated.
const char* lang = language();
char two[3] = {0, 0, 0};
two[0] = lang[0];
two[1] = lang[1] != '\0' ? lang[1] : '\0';
if (strncasecmp(two, "en", 2) != 0) {
char blobPath[64];
snprintf(blobPath, sizeof(blobPath), "/hyphenation/hyph-%c%c.fibh", two[0], two[1]);
HalFile f;
if (Storage.openFileForRead("FIB", blobPath, f)) {
const size_t size = f.fileSize();
hyphBlob_ = makeUniqueNoThrow<uint8_t[]>(size);
if (hyphBlob_ && f.read(hyphBlob_.get(), size) == static_cast<int>(size) &&
hyphenator_.init(hyphBlob_.get(), static_cast<uint32_t>(size))) {
LOG_INF("FIB", "Hyphenation patterns: %s (%u B)", blobPath, static_cast<unsigned>(size));
return;
}
hyphBlob_.reset();
LOG_ERR("FIB", "Failed to load %s; falling back to embedded en-US", blobPath);
}
}
hyphenator_.init(freeink::book::k_hyph_en_us, sizeof(freeink::book::k_hyph_en_us));
}
void BookPaginator::configureLayout(const int16_t pageWidth, const int16_t pageHeight, const int16_t marginLeft,
const int16_t marginRight, const int16_t marginTop, const int16_t marginBottom) {
params_ = freeink::book::LayoutParams{};
params_.pageWidth = pageWidth;
params_.pageHeight = pageHeight;
params_.marginLeft = marginLeft;
params_.marginRight = marginRight;
params_.marginTop = marginTop;
params_.marginBottom = marginBottom;
const uint8_t sizeIndex =
SETTINGS.fontSize < CrossPointSettings::FONT_SIZE_COUNT ? SETTINGS.fontSize : CrossPointSettings::MEDIUM;
params_.baseSizePx = kLadderPx[sizeIndex];
params_.font = &chain_;
params_.stylesheet = (!isTxt_ && sheet_.ruleCount > 0) ? &sheet_ : nullptr;
params_.language = language();
params_.lineSpacingPct = static_cast<uint16_t>(SETTINGS.getReaderLineCompression() * 100.0f + 0.5f);
params_.paragraphSpacingPct = SETTINGS.extraParagraphSpacing ? 150 : 100;
params_.embeddedStyles = SETTINGS.embeddedStyle != 0;
params_.focusReading = SETTINGS.focusReadingEnabled != 0;
params_.hyphenator = (SETTINGS.hyphenationEnabled && hyphenator_.ready()) ? &hyphenator_ : nullptr;
switch (SETTINGS.paragraphAlignment) {
case CrossPointSettings::LEFT_ALIGN:
params_.defaultAlign = TextAlign::Left;
break;
case CrossPointSettings::CENTER_ALIGN:
params_.defaultAlign = TextAlign::Center;
break;
case CrossPointSettings::RIGHT_ALIGN:
params_.defaultAlign = TextAlign::Right;
break;
case CrossPointSettings::BOOK_STYLE:
// Publisher's choice: left when the book CSS is silent.
params_.defaultAlign = TextAlign::Left;
break;
case CrossPointSettings::JUSTIFIED:
default:
params_.defaultAlign = TextAlign::Justify;
break;
}
}
uint32_t BookPaginator::fontFingerprint() const {
uint32_t hash = 2166136261u;
for (uint8_t i = 0; i < ladderCount_; ++i) {
hash = hashMix(hash, static_cast<uint32_t>(ladderFontIds_[i]));
hash = hashMix(hash, ladderSizes_[i]);
}
return hash;
}
uint32_t BookPaginator::generation() const {
return freeink::book::layoutGenerationHash(params_, fontFingerprint());
}
freeink::book::BookStatus BookPaginator::ensureChapter(const uint16_t spineIndex, const BuildProgress& progress) {
const uint32_t gen = generation();
if (!freeink::book::pageCacheName(spineIndex, gen, cacheName_, sizeof(cacheName_))) {
return BookStatus::Unsupported;
}
indexArena_.reset();
curSpine_ = kNoSpine;
BookStatus st = reader_.open(cache_, cacheName_, gen, indexArena_);
if (st == BookStatus::Ok) {
curSpine_ = spineIndex;
return st;
}
const ManifestItem* item = isTxt_ ? nullptr : book_.spineItem(spineIndex);
const freeink::book::ZipEntry* entry = (!isTxt_ && item != nullptr) ? book_.zip().find(item->href) : nullptr;
if (!isTxt_ && entry == nullptr) return BookStatus::NotFound;
if (isTxt_ && spineIndex != 0) return BookStatus::NotFound;
// The pagination working set (layout buffers + one inflate stream + the
// writer's page index) lives only for this call.
auto scratchBuf = makeUniqueNoThrow<uint8_t[]>(kBuildScratchSize);
if (!scratchBuf) {
LOG_ERR("FIB", "OOM: build scratch (%u B, free heap %u)", static_cast<unsigned>(kBuildScratchSize),
static_cast<unsigned>(ESP.getFreeHeap()));
return BookStatus::OutOfMemory;
}
Arena scratch(scratchBuf.get(), kBuildScratchSize);
const uint32_t t0 = millis();
PageCacheWriter writer;
if (!writer.begin(cache_, cacheName_, gen, scratch)) {
return BookStatus::IoError;
}
ProgressSink sink(writer, progress);
uint32_t totalChars = 0;
st = isTxt_ ? ChapterLayout::layoutPlainText(source_, params_, scratch, sink, nullptr, &totalChars)
: ChapterLayout::layout(source_, book_.zip(), *entry, item->href, params_, scratch, sink, nullptr,
&totalChars);
writer.setTotalChars(totalChars);
if (st == BookStatus::Ok && !writer.finish()) st = BookStatus::IoError;
if (st != BookStatus::Ok) {
LOG_ERR("FIB", "Chapter %u layout failed: %d (scratch high water %u B)", spineIndex, static_cast<int>(st),
static_cast<unsigned>(scratch.highWater()));
return st;
}
LOG_INF("FIB", "Chapter %u paginated: %u pages in %ums (scratch high water %u B)", spineIndex, writer.pageCount(),
static_cast<unsigned>(millis() - t0), static_cast<unsigned>(scratch.highWater()));
indexArena_.reset();
st = reader_.open(cache_, cacheName_, gen, indexArena_);
if (st == BookStatus::Ok) curSpine_ = spineIndex;
return st;
}
bool BookPaginator::charForAnchor(const char* fragment, uint32_t* charOut) const {
if (fragment == nullptr || fragment[0] == '\0') return false;
return reader_.charForAnchor(ZipCatalog::hashPath(fragment), charOut);
}
freeink::book::BookStatus BookPaginator::readPage(const uint32_t pageIndex, freeink::book::Page* out) {
pageArena_.reset();
return reader_.readPage(pageIndex, pageArena_, out);
}
int BookPaginator::spineIndexForHref(const char* href) const {
if (href == nullptr || href[0] == '\0' || isTxt_) return -1;
for (size_t s = 0; s < book_.spineCount(); ++s) {
const ManifestItem* item = book_.spineItem(s);
if (item != nullptr && strcmp(item->href, href) == 0) return static_cast<int>(s);
}
return -1;
}
int BookPaginator::fontIdForRunSize(const uint16_t sizePx) const {
const uint16_t q = adapters_[0].quantize(sizePx);
for (uint8_t i = 0; i < ladderCount_; ++i) {
if (ladderSizes_[i] == q) return ladderFontIds_[i];
}
return ladderCount_ > 0 ? ladderFontIds_[0] : 0;
}
+142
View File
@@ -0,0 +1,142 @@
#pragma once
// BookPaginator — one open book's FreeInkBook session: container, fonts,
// layout parameters, and the per-chapter page cache. This is the engine-side
// half of the reader; EpubReaderActivity keeps the UI half (input, menus,
// status bar, refresh cadence) and talks to the engine only through this.
//
// Memory model (ESP32-C3, no PSRAM — all buffers heap-allocated once in
// open() and freed in close()):
// book arena 64 KB ZIP catalog + metadata + spine + TOC (corpus
// high-water 5-40 KB; omnibus containers that exceed
// it fail with a clean OutOfMemory)
// index arena 16 KB current chapter's page index + anchor table
// page arena 16 KB decoded runs of the page being rendered
// build scratch (transient, ~120 KB) allocated only while a chapter
// (re)paginates — the layout engine's whole working set
// Steady-state page turns touch only the page arena (~2 KB used).
#include <FreeInkBook.h>
#include <cache/PageCache.h>
#include <css/Css.h>
#include <layout/ChapterLayout.h>
#include <render/TtfFont.h>
#include <text/Hyphenator.h>
#include <memory>
#include <string>
#include "CpFontAdapter.h"
#include "FreeInkBookStorage.h"
class GfxRenderer;
class BookPaginator {
public:
// Called periodically during a chapter (re)pagination so the UI can show
// an indexing popup / keep the watchdog fed.
struct BuildProgress {
void* ctx;
void (*fn)(void* ctx, uint32_t pagesDone);
}; // value-initialized ({nullptr, nullptr}) by the default argument
BookPaginator() = default;
~BookPaginator() { close(); }
BookPaginator(const BookPaginator&) = delete;
BookPaginator& operator=(const BookPaginator&) = delete;
// Opens the container and builds the font chain. `cacheDir` is the
// per-book directory (".crosspoint/epub_<hash>"). Plain-text files open
// as a one-chapter book with no container.
bool open(const std::string& path, const std::string& cacheDir, GfxRenderer& renderer);
void close();
bool isOpen() const { return open_; }
bool isTxt() const { return isTxt_; }
freeink::book::Book& book() { return book_; }
size_t spineCount() const { return isTxt_ ? 1 : book_.spineCount(); }
const char* language() const;
// Refreshes LayoutParams from SETTINGS and the given content box. Must be
// called before ensureChapter() and after any settings/orientation change;
// a changed generation makes the next ensureChapter() re-paginate.
void configureLayout(int16_t pageWidth, int16_t pageHeight, int16_t marginLeft, int16_t marginRight,
int16_t marginTop, int16_t marginBottom);
// Everything layout-relevant, hashed — the cache key.
uint32_t generation() const;
// Opens the chapter's page cache for the current generation, laying the
// chapter out first when missing or stale. Heavy only on that miss.
freeink::book::BookStatus ensureChapter(uint16_t spineIndex, const BuildProgress& progress = BuildProgress());
bool chapterReady() const { return curSpine_ != kNoSpine; }
uint16_t currentSpine() const { return curSpine_; }
uint32_t pageCount() const { return reader_.pageCount(); }
uint32_t totalChars() const { return reader_.totalChars(); }
uint32_t charStartOfPage(uint32_t pageIndex) const { return reader_.charStart(pageIndex); }
uint32_t pageForChar(uint32_t charOffset) const { return reader_.pageForChar(charOffset); }
// Resolve an id="" fragment in the CURRENT chapter to a char offset.
bool charForAnchor(const char* fragment, uint32_t* charOut) const;
// Decodes one page into the page arena; the returned Page's records stay
// valid until the next readPage() call.
freeink::book::BookStatus readPage(uint32_t pageIndex, freeink::book::Page* out);
// Spine index for a container href (link/TOC targets), -1 when absent.
int spineIndexForHref(const char* href) const;
// Render-path lockstep: the renderer font id for a run's sizePx, quantized
// exactly as CpFontAdapter quantized during layout.
int fontIdForRunSize(uint16_t sizePx) const;
// The ladder rung (px) a run size resolves to — for underline metrics etc.
uint16_t quantizeRunSize(uint16_t sizePx) const { return adapters_[0].quantize(sizePx); }
const freeink::book::LayoutParams& layoutParams() const { return params_; }
private:
static constexpr uint16_t kNoSpine = 0xFFFF;
static constexpr size_t kBookArenaSize = 48 * 1024;
static constexpr size_t kIndexArenaSize = 12 * 1024;
static constexpr size_t kPageArenaSize = 12 * 1024;
static constexpr size_t kSheetArenaSize = 12 * 1024;
static constexpr size_t kBuildScratchSize = 120 * 1024;
bool buildFontChain(GfxRenderer& renderer);
void loadHyphenator();
uint32_t fontFingerprint() const;
SdBookSource source_;
SdCacheStorage cache_;
freeink::book::Book book_;
freeink::book::LayoutParams params_;
freeink::book::PageCacheReader reader_;
freeink::book::FontChain chain_;
CpFontAdapter adapters_[4] = {
CpFontAdapter(EpdFontFamily::REGULAR),
CpFontAdapter(EpdFontFamily::BOLD),
CpFontAdapter(EpdFontFamily::ITALIC),
CpFontAdapter(EpdFontFamily::BOLD_ITALIC),
};
freeink::book::Hyphenator hyphenator_;
std::unique_ptr<uint8_t[]> hyphBlob_; // SD-loaded patterns (non-English books)
std::unique_ptr<uint8_t[]> bookBuf_;
std::unique_ptr<uint8_t[]> indexBuf_;
std::unique_ptr<uint8_t[]> pageBuf_;
std::unique_ptr<uint8_t[]> sheetBuf_;
freeink::book::Arena bookArena_;
freeink::book::Arena indexArena_;
freeink::book::Arena pageArena_;
freeink::book::Arena sheetArena_;
freeink::book::CssStylesheet sheet_{};
// PageCacheReader borrows this for readPage() — must outlive the reader.
char cacheName_[64] = "";
int ladderFontIds_[CpFontAdapter::kMaxLadder] = {};
uint16_t ladderSizes_[CpFontAdapter::kMaxLadder] = {};
uint8_t ladderCount_ = 0;
uint16_t curSpine_ = kNoSpine;
bool open_ = false;
bool isTxt_ = false;
};
+85
View File
@@ -0,0 +1,85 @@
#include "CpFontAdapter.h"
#include <Utf8.h>
bool CpFontAdapter::addSize(const uint16_t sizePx, const EpdFontFamily* family) {
if (family == nullptr || count_ >= kMaxLadder) return false;
if (count_ > 0 && sizePx <= ladder_[count_ - 1].sizePx) return false; // ascending only
ladder_[count_++] = {sizePx, family};
return true;
}
uint16_t CpFontAdapter::quantize(const uint16_t sizePx) const {
if (count_ == 0) return sizePx;
const Rung* best = &ladder_[0];
for (uint8_t i = 1; i < count_; ++i) {
const int cur = ladder_[i].sizePx > sizePx ? ladder_[i].sizePx - sizePx : sizePx - ladder_[i].sizePx;
const int prev = best->sizePx > sizePx ? best->sizePx - sizePx : sizePx - best->sizePx;
if (cur < prev) best = &ladder_[i]; // ties keep the smaller rung
}
return best->sizePx;
}
const EpdFontFamily* CpFontAdapter::familyFor(const uint16_t sizePx) const {
if (count_ == 0) return nullptr;
const uint16_t q = quantize(sizePx);
for (uint8_t i = 0; i < count_; ++i) {
if (ladder_[i].sizePx == q) return ladder_[i].family;
}
return ladder_[0].family;
}
int16_t CpFontAdapter::advance(const uint32_t codepoint, const uint16_t sizePx, uint8_t) {
// GfxRenderer does not advance the cursor for combining marks (they center
// over the previous base glyph); report the same.
if (utf8IsCombiningMark(codepoint)) return 0;
const EpdFontFamily* family = familyFor(sizePx);
if (family == nullptr) return 0;
const EpdGlyph* glyph = family->getGlyph(codepoint, style_);
return glyph != nullptr ? static_cast<int16_t>(fp4::toPixel(glyph->advanceX)) : 0;
}
int16_t CpFontAdapter::lineHeight(const uint16_t sizePx) {
// advanceY is the newline distance GfxRenderer::getLineHeight() reports —
// the same figure the legacy reader spaced lines with (CrossPoint parity).
const EpdFontFamily* family = familyFor(sizePx);
return family != nullptr ? static_cast<int16_t>(family->getData(style_)->advanceY) : 0;
}
int16_t CpFontAdapter::ascent(const uint16_t sizePx) {
const EpdFontFamily* family = familyFor(sizePx);
return family != nullptr ? static_cast<int16_t>(family->getData(style_)->ascender) : 0;
}
int16_t CpFontAdapter::kerning(const uint32_t left, const uint32_t right, const uint16_t sizePx,
uint8_t) {
if (utf8IsCombiningMark(left) || utf8IsCombiningMark(right)) return 0;
const EpdFontFamily* family = familyFor(sizePx);
if (family == nullptr) return 0;
const EpdGlyph* leftGlyph = family->getGlyph(left, style_);
if (leftGlyph == nullptr) return 0;
const int32_t advFP = leftGlyph->advanceX; // 12.4 fixed-point
const int32_t kernFP = family->getKerning(left, right, style_); // 4.4 fixed-point
// Differential-rounding parity: layout adds advance(left) + kerning(left,
// right); returning the delta between the renderer's fused snap and the
// advance's own snap makes the sum equal the renderer's cursor step.
return static_cast<int16_t>(fp4::toPixel(advFP + kernFP) - fp4::toPixel(advFP));
}
uint32_t CpFontAdapter::ligature(const uint32_t left, const uint32_t right, uint8_t) {
// Size-independent in cpfonts; use the largest rung's table.
if (count_ == 0) return 0;
return ladder_[count_ - 1].family->getLigature(left, right, style_);
}
bool CpFontAdapter::hasGlyph(const uint32_t codepoint) const {
if (count_ == 0) return false;
return ladder_[count_ - 1].family->hasGlyph(codepoint, style_);
}
const freeink::book::GlyphBitmap* CpFontAdapter::rasterize(uint32_t, uint16_t) {
// CrossPoint draws page records with GfxRenderer (glyph groups, SD overflow
// fetch, 2-bit AA all stay in the renderer); the engine's PageRenderer is
// not used, so nothing ever rasterizes through this adapter.
return nullptr;
}
+62
View File
@@ -0,0 +1,62 @@
#pragma once
// CpFontAdapter — one .cpfont style (regular/bold/italic/bold-italic) exposed
// through FreeInkBook's RenderFont interface, so the engine lays out with the
// exact metrics GfxRenderer will draw with.
//
// .cpfonts exist on a fixed size ladder (12/14/16/18 px). The engine requests
// arbitrary sizePx (headings scale the base size); every request is quantized
// to the nearest ladder entry identically in ALL metrics, and the render path
// quantizes the same way when picking a font id, so measurement and drawing
// can never disagree about which font a run uses.
//
// Width parity is exact by construction: GfxRenderer advances the cursor with
// differential fixed-point rounding — each step is toPixel(advFP(prev) +
// kernFP(prev, cur)). This adapter reports advance(cp) = toPixel(advFP(cp))
// and kerning(l, r) = toPixel(advFP(l) + kernFP(l, r)) - toPixel(advFP(l));
// layout's per-glyph sum then telescopes to precisely the renderer's total.
// (One knowingly accepted divergence: the renderer kerns across combining
// marks against the base letter; layout sees the mark as `prev` and skips
// that kern — sub-pixel, and only on mark-bearing text.)
//
// Metrics-only and host-compilable (EpdFont + Utf8 + FreeInkBook headers).
// rasterize() intentionally returns nullptr: CrossPoint renders page records
// through GfxRenderer's own glyph pipeline (see the migration renderer
// contract), never through the engine's PageRenderer.
#include <BookFont.h>
#include <EpdFontFamily.h>
class CpFontAdapter : public freeink::book::RenderFont {
public:
static constexpr uint8_t kMaxLadder = 6;
explicit CpFontAdapter(EpdFontFamily::Style style = EpdFontFamily::REGULAR) : style_(style) {}
// Register one ladder rung. Call in ascending sizePx order.
bool addSize(uint16_t sizePx, const EpdFontFamily* family);
// The ladder size a request resolves to (also used by the render path to
// pick the matching font id — keep the two in lockstep).
uint16_t quantize(uint16_t sizePx) const;
// freeink::book::RenderFont
int16_t advance(uint32_t codepoint, uint16_t sizePx, uint8_t styleFlags) override;
int16_t lineHeight(uint16_t sizePx) override;
int16_t ascent(uint16_t sizePx) override;
int16_t kerning(uint32_t left, uint32_t right, uint16_t sizePx, uint8_t styleFlags) override;
uint32_t ligature(uint32_t left, uint32_t right, uint8_t styleFlags) override;
bool hasGlyph(uint32_t codepoint) const override;
const freeink::book::GlyphBitmap* rasterize(uint32_t codepoint, uint16_t sizePx) override;
private:
const EpdFontFamily* familyFor(uint16_t sizePx) const;
struct Rung {
uint16_t sizePx;
const EpdFontFamily* family;
};
Rung ladder_[kMaxLadder] = {};
uint8_t count_ = 0;
EpdFontFamily::Style style_;
};
@@ -25,6 +25,7 @@
#include "EpubReaderFootnotesActivity.h"
#include "EpubReaderPercentSelectionActivity.h"
#include "EpubReaderUtils.h"
#include "FreeInkBookStorage.h"
#include "KOReaderCredentialStore.h"
#include "KOReaderSyncActivity.h"
#include "MappedInputManager.h"
+122
View File
@@ -0,0 +1,122 @@
#pragma once
// FreeInkBook storage adapters — bind the engine's BookSource/CacheStorage
// interfaces to HalStorage (all SD access must go through the HAL mutex).
// Pattern follows freeink-books' BookStorageAdapters.h with CrossPoint's
// torn-write-safe temp+rename commit.
#include <BookStorage.h>
#include <HalStorage.h>
#include <Logging.h>
#include <cstdio>
// Random access over one book file on the SD card. The file stays open for
// the book's lifetime; every readAt takes the storage mutex via HalFile.
class SdBookSource : public freeink::book::BookSource {
public:
bool open(const char* path) {
if (!Storage.openFileForRead("FIBSRC", path, file_)) return false;
size_ = file_.fileSize64();
return size_ > 0;
}
void close() { file_.close(); }
int32_t readAt(uint64_t offset, void* dst, uint32_t len) override {
if (!file_.isOpen() || !file_.seek64(offset)) return -1;
return file_.read(dst, len);
}
uint64_t size() const override { return size_; }
private:
HalFile file_;
uint64_t size_ = 0;
};
// Layout-cache files inside one book's cache directory. Writes stream to a
// temp name and commit via rename, so an interrupted write leaves the old
// file or none — never a torn one (the engine additionally verifies a footer
// magic). Reads keep the last-touched file open: page turns are then one
// seek+read instead of a directory walk per call.
class SdCacheStorage : public freeink::book::CacheStorage {
public:
// `dir` is the per-book cache directory (e.g. ".crosspoint/epub_<hash>").
void setDir(const char* dir) {
snprintf(dir_, sizeof(dir_), "%s", dir);
Storage.ensureDirectoryExists(dir_);
closeRead();
}
bool exists(const char* name) override { return Storage.exists(path(name)); }
bool remove(const char* name) override {
invalidateRead(name);
return Storage.remove(path(name));
}
int64_t fileSize(const char* name) override {
if (!ensureReadOpen(name)) return -1;
return static_cast<int64_t>(readFile_.fileSize64());
}
int32_t readAt(const char* name, uint32_t offset, void* dst, uint32_t len) override {
if (!ensureReadOpen(name) || !readFile_.seekSet(offset)) return -1;
return readFile_.read(dst, len);
}
bool beginWrite(const char* name) override {
snprintf(commitPath_, sizeof(commitPath_), "%s/%s", dir_, name);
invalidateRead(name);
if (!Storage.openFileForWrite("FIBCACHE", path(kTempName), write_)) {
LOG_ERR("FIBCACHE", "beginWrite failed: %s", commitPath_);
return false;
}
return true;
}
bool write(const void* data, uint32_t len) override {
return write_.isOpen() && write_.write(data, len) == len;
}
bool endWrite() override {
if (!write_.isOpen()) return false;
write_.close(); // must close before rename (DESTRUCTOR_CLOSES_FILE covers scope exit only)
Storage.remove(commitPath_); // may not exist; rename below is the commit point
if (!Storage.rename(path(kTempName), commitPath_)) {
LOG_ERR("FIBCACHE", "commit rename failed: %s", commitPath_);
return false;
}
return true;
}
private:
static constexpr const char* kTempName = "_tmp.fibp";
const char* path(const char* name) {
snprintf(pathBuf_, sizeof(pathBuf_), "%s/%s", dir_, name);
return pathBuf_;
}
bool ensureReadOpen(const char* name) {
if (readFile_.isOpen() && strncmp(readName_, name, sizeof(readName_)) == 0) return true;
closeRead();
if (!Storage.openFileForRead("FIBCACHE", path(name), readFile_)) return false;
snprintf(readName_, sizeof(readName_), "%s", name);
return true;
}
void invalidateRead(const char* name) {
if (readFile_.isOpen() && strncmp(readName_, name, sizeof(readName_)) == 0) closeRead();
}
void closeRead() {
if (readFile_.isOpen()) readFile_.close();
readName_[0] = '\0';
}
char dir_[96] = "";
char pathBuf_[192];
char commitPath_[192];
char readName_[80] = "";
HalFile readFile_;
HalFile write_;
};
+1
View File
@@ -43,3 +43,4 @@ add_subdirectory(release_json_parser)
add_subdirectory(differential_rounding)
add_subdirectory(hyphenation_eval)
add_subdirectory(utf8_compose)
add_subdirectory(cpfont_adapter)
+34
View File
@@ -0,0 +1,34 @@
# CpFontAdapter binds .cpfont metrics to FreeInkBook's RenderFont interface;
# the suite needs the engine's freestanding headers. Prefer the submodule;
# fall back to the sibling working checkout while the submodule pin predates
# libs/book (drop the fallback once the pin advances).
set(FREEINK_BOOK_INCLUDE "${REPO_ROOT}/freeink-sdk/libs/book/FreeInkBook/include")
if(NOT EXISTS "${FREEINK_BOOK_INCLUDE}")
set(FREEINK_BOOK_INCLUDE "$ENV{HOME}/GitHub/freeink-sdk/libs/book/FreeInkBook/include")
endif()
if(NOT EXISTS "${FREEINK_BOOK_INCLUDE}")
message(WARNING "FreeInkBook headers not found - skipping CpFontAdapterTest")
else()
add_executable(CpFontAdapterTest
CpFontAdapterTest.cpp
${REPO_ROOT}/src/activities/reader/CpFontAdapter.cpp
${REPO_ROOT}/lib/EpdFont/EpdFont.cpp
${REPO_ROOT}/lib/EpdFont/EpdFontFamily.cpp
${REPO_ROOT}/lib/Utf8/Utf8.cpp
)
target_include_directories(CpFontAdapterTest PRIVATE
${REPO_ROOT}/src/activities/reader
${REPO_ROOT}/lib/EpdFont
${REPO_ROOT}/lib/Utf8
${FREEINK_BOOK_INCLUDE}
)
target_link_libraries(CpFontAdapterTest PRIVATE
crosspoint_test_common
GTest::gtest_main
)
gtest_discover_tests(CpFontAdapterTest)
endif()
+206
View File
@@ -0,0 +1,206 @@
#include <gtest/gtest.h>
#include <cstdint>
#include "CpFontAdapter.h"
#include "lib/EpdFont/EpdFont.h"
#include "lib/EpdFont/EpdFontData.h"
#include "lib/EpdFont/EpdFontFamily.h"
#include "lib/Utf8/Utf8.h"
// ============================================================================
// Synthetic fonts (same convention as DifferentialRoundingTest): metrics
// chosen so per-glyph rounding and differential rounding disagree unless the
// adapter's kerning-delta trick is applied.
//
// Glyphs: 'T' (0x54), 'a' (0x61), 'o' (0x6F), 'x' (0x78), U+FFFD.
// Kern pairs (4.4 FP): T->a -5, T->o -7, o->a -2, o->o -3.
// Ligature: 'T'+'x' -> U+E000 (private use; also a glyph in the font).
// ============================================================================
namespace {
// clang-format off
const EpdGlyph kGlyphs16[] = {
/* 0 'T' */ { 8, 12, 137, 0, 12, 0, 0 },
/* 1 'a' */ { 7, 8, 130, 0, 8, 0, 0 },
/* 2 'o' */ { 8, 8, 145, 0, 8, 0, 0 },
/* 3 'x' */ { 7, 8, 136, 0, 8, 0, 0 },
/* 4 U+E000 */ { 12, 12, 200, 0, 12, 0, 0 },
/* 5 U+FFFD */ { 9, 12, 160, 0, 12, 0, 0 },
};
const EpdUnicodeInterval kIntervals16[] = {
{ 0x54, 0x54, 0 },
{ 0x61, 0x61, 1 },
{ 0x6F, 0x6F, 2 },
{ 0x78, 0x78, 3 },
{ 0xE000, 0xE000, 4 },
{ 0xFFFD, 0xFFFD, 5 },
};
const EpdKernClassEntry kKernLeft[] = { { 0x54, 1 }, { 0x6F, 2 } };
const EpdKernClassEntry kKernRight[] = { { 0x61, 1 }, { 0x6F, 2 } };
const int8_t kKernMatrix[] = { -5, -7, -2, -3 };
const EpdLigaturePair kLigatures[] = {
{ (0x54u << 16) | 0x78u, 0xE000 }, // 'T' + 'x'
};
// clang-format on
EpdFontData makeFontData(const EpdGlyph* glyphs, const EpdUnicodeInterval* intervals,
uint32_t intervalCount, uint8_t advanceY, int ascender, int descender) {
EpdFontData d{};
d.bitmap = nullptr;
d.glyph = glyphs;
d.intervals = intervals;
d.intervalCount = intervalCount;
d.advanceY = advanceY;
d.ascender = ascender;
d.descender = descender;
d.kernLeftClasses = kKernLeft;
d.kernRightClasses = kKernRight;
d.kernMatrix = kKernMatrix;
d.kernLeftEntryCount = 2;
d.kernRightEntryCount = 2;
d.kernLeftClassCount = 2;
d.kernRightClassCount = 2;
d.ligaturePairs = kLigatures;
d.ligaturePairCount = 1;
return d;
}
// A second, wider font standing in for the 12 px ladder rung so quantization
// is observable ('T' advance differs).
const EpdGlyph kGlyphs12[] = {
/* 0 'T' */ {6, 9, 96, 0, 9, 0, 0}, // 6.0 px exactly
};
const EpdUnicodeInterval kIntervals12[] = {{0x54, 0x54, 0}};
// The reference: GfxRenderer's differential-rounding cursor walk
// (drawText/getTextWidth in GfxRenderer.cpp) — each step snaps
// (prev advance FP + kern FP) as one unit.
int rendererWidth(const EpdFontFamily& family, const uint32_t* cps, int n,
EpdFontFamily::Style style) {
int width = 0;
int32_t prevAdvanceFP = 0;
uint32_t prevCp = 0;
for (int i = 0; i < n; ++i) {
const uint32_t cp = cps[i];
if (prevCp != 0) {
width += fp4::toPixel(prevAdvanceFP + family.getKerning(prevCp, cp, style));
}
const EpdGlyph* glyph = family.getGlyph(cp, style);
prevAdvanceFP = glyph ? glyph->advanceX : 0;
prevCp = cp;
}
width += fp4::toPixel(prevAdvanceFP);
return width;
}
// The engine's accounting: advance(cp) plus kerning(prev, cp) per glyph
// (ChapterLayout::advanceFor).
int layoutWidth(CpFontAdapter& font, const uint32_t* cps, int n, uint16_t sizePx) {
int width = 0;
uint32_t prevCp = 0;
for (int i = 0; i < n; ++i) {
width += font.advance(cps[i], sizePx, 0);
if (prevCp != 0) width += font.kerning(prevCp, cps[i], sizePx, 0);
prevCp = cps[i];
}
return width;
}
class CpFontAdapterTest : public ::testing::Test {
protected:
CpFontAdapterTest()
: data16_(makeFontData(kGlyphs16, kIntervals16, 6, 20, 14, -5)),
data12_(makeFontData(kGlyphs12, kIntervals12, 1, 15, 11, -4)),
font16_(&data16_),
font12_(&data12_),
family16_(&font16_),
family12_(&font12_) {
adapter_.addSize(12, &family12_);
adapter_.addSize(16, &family16_);
}
EpdFontData data16_, data12_;
EpdFont font16_, font12_;
EpdFontFamily family16_, family12_;
CpFontAdapter adapter_;
};
TEST_F(CpFontAdapterTest, AdvanceSnapsFixedPointPerGlyph) {
// 137 FP -> 9 px, 130 -> 8, 145 -> 9, 136 -> 9 (round-half-up at 8/16).
EXPECT_EQ(adapter_.advance('T', 16, 0), 9);
EXPECT_EQ(adapter_.advance('a', 16, 0), 8);
EXPECT_EQ(adapter_.advance('o', 16, 0), 9);
EXPECT_EQ(adapter_.advance('x', 16, 0), 9);
}
TEST_F(CpFontAdapterTest, KerningDeltaMatchesRendererDifferentialRounding) {
// Every string the renderer can draw must measure to the renderer's own
// differentially-rounded width — the telescoping identity the adapter's
// kerning() implements. "oo" (advance frac 1, kern -3) is the case where
// naive per-glyph rounding diverges.
const uint32_t oo[] = {'o', 'o'};
const uint32_t tao[] = {'T', 'a', 'o'};
const uint32_t tooao[] = {'T', 'o', 'o', 'a', 'o'};
EXPECT_EQ(layoutWidth(adapter_, oo, 2, 16), rendererWidth(family16_, oo, 2, EpdFontFamily::REGULAR));
EXPECT_EQ(layoutWidth(adapter_, tao, 3, 16), rendererWidth(family16_, tao, 3, EpdFontFamily::REGULAR));
EXPECT_EQ(layoutWidth(adapter_, tooao, 5, 16),
rendererWidth(family16_, tooao, 5, EpdFontFamily::REGULAR));
}
TEST_F(CpFontAdapterTest, KerningPairValues) {
// kerning(T,o) = toPixel(137 + (-7)) - toPixel(137) = 8 - 9 = -1.
EXPECT_EQ(adapter_.kerning('T', 'o', 16, 0), -1);
// kerning(o,o) = toPixel(145 - 3) - toPixel(145) = 9 - 9 = 0.
EXPECT_EQ(adapter_.kerning('o', 'o', 16, 0), 0);
// No kern class pair -> 0.
EXPECT_EQ(adapter_.kerning('a', 'x', 16, 0), 0);
}
TEST_F(CpFontAdapterTest, QuantizesToNearestRungInMetricsToo) {
EXPECT_EQ(adapter_.quantize(12), 12);
EXPECT_EQ(adapter_.quantize(13), 12);
EXPECT_EQ(adapter_.quantize(14), 12); // tie keeps the smaller rung
EXPECT_EQ(adapter_.quantize(15), 16);
EXPECT_EQ(adapter_.quantize(24), 16); // above the ladder clamps to the top
// 'T' at 12 px comes from the 12 px font (96 FP -> 6 px), not a scale.
EXPECT_EQ(adapter_.advance('T', 12, 0), 6);
EXPECT_EQ(adapter_.advance('T', 13, 0), 6);
EXPECT_EQ(adapter_.advance('T', 24, 0), 9);
EXPECT_EQ(adapter_.lineHeight(13), 15);
EXPECT_EQ(adapter_.lineHeight(24), 20);
EXPECT_EQ(adapter_.ascent(13), 11);
EXPECT_EQ(adapter_.ascent(24), 14);
}
TEST_F(CpFontAdapterTest, HasGlyphIsNotFooledByReplacementFallback) {
EXPECT_TRUE(adapter_.hasGlyph('T'));
EXPECT_TRUE(adapter_.hasGlyph(0xFFFD));
// 'q' is missing; getGlyph would return U+FFFD, hasGlyph must say no.
EXPECT_FALSE(adapter_.hasGlyph('q'));
EXPECT_NE(family16_.getGlyph('q', EpdFontFamily::REGULAR), nullptr);
}
TEST_F(CpFontAdapterTest, LigatureLookup) {
EXPECT_EQ(adapter_.ligature('T', 'x', 0), 0xE000u);
EXPECT_EQ(adapter_.ligature('T', 'a', 0), 0u);
}
TEST_F(CpFontAdapterTest, CombiningMarksDoNotAdvance) {
// U+0301 combining acute: the renderer centers it over the base glyph and
// moves the cursor zero pixels; layout must agree.
EXPECT_EQ(adapter_.advance(0x0301, 16, 0), 0);
EXPECT_EQ(adapter_.kerning('a', 0x0301, 16, 0), 0);
}
TEST_F(CpFontAdapterTest, MissingGlyphAdvanceMatchesRendererReplacementDraw) {
// The renderer draws U+FFFD for a missing codepoint; layout must reserve
// the replacement glyph's width (160 FP -> 10 px), not zero.
EXPECT_EQ(adapter_.advance('q', 16, 0), 10);
}
} // namespace