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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "expat.h"
|
||||
#include <epub/Expat.h> // FreeInkBook's vendored expat
|
||||
|
||||
class ContainerParser final : public Print {
|
||||
enum ParserState {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "Epub.h"
|
||||
#include "expat.h"
|
||||
#include <epub/Expat.h> // FreeInkBook's vendored expat
|
||||
|
||||
class BookMetadataCache;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <Print.h>
|
||||
#include <expat.h>
|
||||
#include <epub/Expat.h> // FreeInkBook's vendored expat
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <Print.h>
|
||||
#include <expat.h>
|
||||
#include <epub/Expat.h> // FreeInkBook's vendored expat
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <Print.h>
|
||||
#include <expat.h>
|
||||
#include <epub/Expat.h> // FreeInkBook's vendored expat
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
@@ -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,
|
||||
@@ -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
|
||||
@@ -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,
|
||||
@@ -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
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "expat",
|
||||
"version": "2.7.3",
|
||||
"build": {
|
||||
"srcFilter": [
|
||||
"+<xmlparse.c>",
|
||||
"+<xmlrole.c>",
|
||||
"+<xmltok.c>"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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 */
|
||||
@@ -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,
|
||||
@@ -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 */
|
||||
File diff suppressed because it is too large
Load Diff
-1108
File diff suppressed because it is too large
Load Diff
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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>
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user